Whenever you call a JNI method, here FindClass(), GetMethodID(),
CallObjectMethod(), etc.. an exception may occur, in which case the method will
return NULL. If this occurs, the VM enters a special state, and you must not
call any other JNI method (apart from a very few one) until the exception gets
cleared. If you don't respect this rule, unexpected problems may happen.
http://java.sun.com/docs/books/jni/html/exceptions.html#26383
http://java.sun.com/docs/books/jni/html/design.html#2193
The fact that none of the CallObjectMethod() parameters are NULL doesn't
necessarily means that none of the previous calls returned NULL. Remember, if
you don't check for NULL result at every step, unexpected stuff may happen.
Adding such proper error checking is the first thing to do here IMO.
--
Olivier
--
You received this message because you are subscribed to the Google Groups "android-ndk" group.
To post to this group, send email to andro...@googlegroups.com.
To unsubscribe from this group, send email to android-ndk...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/android-ndk?hl=en.
I see.
>
> According to the documentation, if a JNI method returned NULL, an
> exception was thrown and needs to be cleared.
> But, is it possible that no NULLs are returned yet still an Exception is
> thrown?
http://java.sun.com/docs/books/jni/html/exceptions.html#26379
Notice the "Most":
"Most JNI functions use a distinct return value (such as NULL) to indicate that
an error has occurred."
And then:
"When using a JNI function whose return value cannot flag that an error has
occurred, native code must rely on the raised exception to do error checks. The
JNI function that performs checks for a pending exception in the current thread
is ExceptionOccurred. (ExceptionCheck was also added in Java 2 SDK release 1.2.)"
But unless I'm wrong, all functions that you are using can return NULL. You
don't call say a method returning jint.
I have used getDeviceId() a lot in Java, plenty of users, plenty of devices,
including many tablets. It doesn't crash AFAIK. I can't remember any feedback
from a Nook user though.
If you do the same thing in Java, does it crash?
Also, what is this cached_java_object exactly? An Activity, right? Do you
properly hold a global reference on it? Do you use it in the same thread where
it was instantiated (the main loop that is) ?
Have you checked the bug mentioned by alan?
--
Olivier
ExceptionCheck
. However, it is more efficient to check for the distinct error return value instead.
--
Olivier
Yes, ExceptionCheck() is only useful when you deal with functions which can't
return NULL, such a those which return an integer. But it's indeed not the
problem here. I just mentioned this for clarification.
By the way, I should have asked about this first, but what do you get in logcat?
A stack trace could help. IIRC, I once understood a weird crash by running the
NDK's addr2line on libdvm.so.
> When I do the same thing in Java I get "000000".
So, it doesn't crash in Java.
According to what alan mentioned and a bit of intuition, here's what I would try
here: create say a PlatformUtil class in Java, and add a getDeviceId(Context)
static method in there which hides the details of accessing the TelephonyManager
and returns the id string or NULL. And call that method with JNI.
I know it sounds like a workaround, but it could also help understand things I
guess.
> cached_java_object is a global reference to an Activity, and no, it is
> used in another thread, but as far as I know this is allowed. You can
> access global referenced variables from different threads.
Yes, as long as the thread is attached to the VM:
http://android.git.kernel.org/?p=platform/dalvik.git;a=blob_plain;f=docs/jni-tips.html;hb=HEAD#Threads
Olivier
Olivier