GetMethodID() does not return

1,043 views
Skip to first unread message

Christian Linne

unread,
Jun 8, 2010, 2:23:01 AM6/8/10
to andro...@googlegroups.com
Hi,
 
as mentioned above, I have a problem with GetMethodID from JNI. It seems that it does not return, and even causes no error, just nothing seems to happen.
Code is the following:
[...]

if

(!(jjvm->AttachCurrentThread(&jjvm, &env, NULL))) {

   BT_Debug(ANDROID_LOG_DEBUG, "Thread successfully attached.");

   message = (*env)->NewByteArray(env, bufferlen);

   BT_Debug(ANDROID_LOG_DEBUG,

"Byte-Array created.");

// ... and fill it

   (*env)->SetByteArrayRegion(env, message, 0, bufferlen,(

const jbyte *) ((BYTE*) buffer));

   BT_Debug(ANDROID_LOG_DEBUG,

"Byte-Array filled.");

   mid = (*env)->GetMethodID(env, jcls, "sendMessage", "([B)V");

   BT_Debug(ANDROID_LOG_DEBUG, "Method-ID fetched.");

   if (mid > 0) {

      (*env)->CallStaticVoidMethod(env, jcls, mid, message);

      BT_Debug(ANDROID_LOG_DEBUG, " 'sendMessage' called.");

   }

   BT_Debug(ANDROID_LOG_DEBUG, "Method-call 'storeMessage' settled.");

   return bufferlen;

}

[...]

Note:
- jjvm is a reference to the JavaVM (type "JavaVM")
- jcls is a reference to the class that inherits the method "sendMessage" (type "jclass")
- both seem to be correct - they have been created and stored previously
- message is a jbyteArray
- mid is a jmethodID
- BT_Debug(...) creates an entry on the logcat (just mapped for compatibility
- "Byte-Array filled." is the last message I receive on the logcat, just nothing happens afterwards
 
Any ideas why GetMethodID does not return?
 
 
Regards,
 
christian.l

Divkis

unread,
Jun 8, 2010, 2:49:41 AM6/8/10
to android-ndk
Hi,

On Jun 8, 11:23 am, Christian Linne <christian.li...@googlemail.com>
wrote:
> Hi,
>
> as mentioned above, I have a problem with GetMethodID from JNI. It seems
> that it does not return, and even causes no error, just nothing seems to
> happen.
> Note:
> - jjvm is a reference to the JavaVM (type "JavaVM")
> - jcls is a reference to the class that inherits the method "sendMessage"
> (type "jclass")
> - both seem to be correct - they have been created and stored previously

Have you stored the object of jclass as a global reference? Without
which getting the class reference would be a local reference and might
get garbage collected by the time you call the getMethodID. But in
such a case the exception should be thrown by the VM which you can
print by calling env->ExceptionDescribe(); before exiting the
function.


Hope that helps,
Divkis

Christian Linne

unread,
Jun 8, 2010, 3:18:56 AM6/8/10
to andro...@googlegroups.com
Hi,

2010/6/8 Divkis <divick....@gmail.com>

--
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 cannot get a NewGlobalRef(...) for the jclass - reference I stored previously, because NewGlobalRef(...) only exists for jobject (according to the jni.h ) -  I only use methods in Java that call do the native part which are static, so the jclass - reference is handled over, and I store it on the first time I do so.
I have already tried to find out if there was any exception, but even  " (*env)->ExceptionOccurred(env) " is not true. As mentioned before, it seems that it just stops immediately and does not do anything afterwards.

I have already checked if the Java-Thread (which handles over some data to the native part)  that is created and started parallel to the part I have mentioned above causes any problems - and it obviously does not.
 
It is quite curious that just nothing seems to happen...
 
 
Regards,
 
christian.l

Christian Linne

unread,
Jun 8, 2010, 3:34:22 AM6/8/10
to andro...@googlegroups.com
Oh, it seems that I'm puzzled sometimes... NewGlobalRef(....) also works for jclass using an explicit conversion.
I have stored it with

cls =(jclass)( env->NewGlobalRef(jcls) );

with jcls being the jclass - reference that is handled over with the first call from Java, and this class inherits everything that calls from Java to C/C++ and viceversa.

But that just does not solve the problem.

(Besides, nevermind about that mix of C and C++ - Code - I did not start this project, I just have to work with it... )



2010/6/8 Christian Linne <christi...@googlemail.com>



--
_________
Mit freundlichen Grüßen
Christian Linne

Mail (Privat): linn...@aol.com
Mail (Offiziell): Christi...@googlemail.com, Christi...@student.uni-kassel.de
ICQ: 293253013

fadden

unread,
Jun 8, 2010, 4:49:39 PM6/8/10
to android-ndk
On Jun 7, 11:49 pm, Divkis <divick.kish...@gmail.com> wrote:
> Have you stored the object of jclass as a global reference? Without
> which getting the class reference would be a local reference and might
> get garbage collected by the time you call the getMethodID.  But in
> such a case the exception should be thrown by the VM which you can
> print by calling env->ExceptionDescribe(); before exiting the
> function.

The VM doesn't throw anything if you try to use an invalid object
reference. It just crashes. The point of JNI is to be fast, and if
the VM has to double-check everything you pass in, it'll be slower.

If you want safe-but-slow, enable CheckJNI:
http://android.git.kernel.org/?p=platform/dalvik.git;a=blob_plain;f=docs/jni-tips.html;hb=HEAD
http://android.git.kernel.org/?p=platform/dalvik.git;a=blob_plain;f=docs/embedded-vm-control.html;hb=HEAD

That'll double-check your objects.

The C++ version of jni.h specifies jobject / jclass / jarray / etc. as
an object hierarchy; in C you get to type-cast things to and from
jobject when using NewGlobalRef.

If GetMethodID is not returning, then either the thread has crashed
(check the "logcat" output) or some corruption in internal VM data
structures has caused it to spin in an infinite loop. Does the
behavior change if you do the GetMethodID above the SetByteArrayRegion
call?

Christian Linne

unread,
Jun 9, 2010, 2:14:33 AM6/9/10
to andro...@googlegroups.com
There is no output on the logcat that according to a crash of the VM, there is just nothing - that is why I'm wondering about that.
 
I have tried to get the method-ID before setting the byte-array (even before creating it), but the behaviour does not change anyway - it stops when calling the method ( I have changed that to GetStaticMethodID, because the method I want to use is static ) and just does nothing any more. The only logcat-informations that appear afterwards are the ones created from another thread (started from Java).
Might there be a way to check internal VM data for corruption? Anything that helps is welcome.

2010/6/8 fadden <fad...@android.com>
--
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.

fadden

unread,
Jun 10, 2010, 1:49:54 AM6/10/10
to android-ndk
On Jun 8, 11:14 pm, Christian Linne <christian.li...@googlemail.com>
wrote:
> Might there be a way to check internal VM data for corruption? Anything that
> helps is welcome.

Did you try enabling CheckJNI?

fadden

unread,
Jun 10, 2010, 1:51:57 AM6/10/10
to android-ndk
On Jun 8, 11:14 pm, Christian Linne <christian.li...@googlemail.com>
wrote:
> Might there be a way to check internal VM data for corruption? Anything that
> helps is welcome.

Christian Linne

unread,
Jun 10, 2010, 6:08:32 AM6/10/10
to andro...@googlegroups.com
Anytime I try to do so, the real kind "Permission denied" returns - I'm working with usual devices (Archos 5 (1.6) and Nexus One (2.2). I cannot really use a root-shell on it - "cannot run as root in production builds", but that is the precondition to change this option, as far as I know. Trying to run this on the Nexus One does not only stop, it causes a segmentation fault and the message "unexpected resume of com.android.launcher2 ...", which is quite more irritating.

2010/6/10 fadden <fad...@android.com>
--

fadden

unread,
Jun 11, 2010, 8:06:33 PM6/11/10
to android-ndk
On Jun 10, 3:08 am, Christian Linne <christian.li...@googlemail.com>
wrote:
> Anytime I try to do so, the real kind "Permission denied" returns - I'm
> working with usual devices (Archos 5 (1.6) and Nexus One (2.2). I cannot
> really use a root-shell on it - "cannot run as root in production builds",
> but that is the precondition to change this option, as far as I know. Trying
> to run this on the Nexus One does not only stop, it causes a segmentation
> fault and the message "unexpected resume of com.android.launcher2 ...",
> which is quite more irritating.

Try "setprop debug.checkjni 1". Make sure your app isn't running;
it'll take effect the next time your app is launched.

Christian Linne

unread,
Jun 14, 2010, 4:06:44 AM6/14/10
to andro...@googlegroups.com
I've tried that, but CheckJNI is still marked as OFF (according to the info on the logcat).
 
But for now, this issue is resolved, I've changed the way to get and access the JavaVM-reference, and for now, it works fine. Seems that no one will ever know why, but thanks for any help on this issue.
2010/6/12 fadden <fad...@android.com>

--

fadden

unread,
Jun 15, 2010, 1:48:54 PM6/15/10
to android-ndk
On Jun 14, 1:06 am, Christian Linne <christian.li...@googlemail.com>
wrote:
> I've tried that, but CheckJNI is still marked as OFF (according to the info
> on the logcat).

That's normal -- that flag doesn't get checked until the app is
forked, and the "CheckJNI" message comes up much earlier (during
zygote initialization). The debug.checkjni property isn't an
"official" feature, for this and other reasons.
Reply all
Reply to author
Forward
0 new messages