JNI crashes when calling CallVoidMethod

I am trying to call a java method from my own C code in an Android application. It sounds pretty simple using JNI, but my code always crashes when the method itself is finally called. Here is my code: Native C code:

JNIEXPORT void JNICALL Java_com_path_to_my_package_renderStuff(JNIEnv* env, jobject jobj){ //... jclass clazz = env->FindClass("com/path/to/the/class"); jmethodID showCar = env->GetMethodID(clazz,"showCar","()V" ); env->CallVoidMethod(jobj,showCar); //If I comment this out, it won't crash //... } 

Java Code:

 public void showCar(){ doSomething() } 

doSomething () is not even reached, I can set a breakpoint there that will never be deleted. And, as stated above, as soon as I comment on the CallVoidMethod call, it will not crash, but it will not explicitly call showCar (). Any clues?

+8
android jni
source share
1 answer

4 ideas for you:

...

jclass clazz = env-> FindClass ("com / path / to / the / class");

Can you confirm that the name is not "com / path / to / the / MyClass", where the class name is upper case of the 1st character, and obviously the name "class" is a reserved word. There is a slight discrepancy between using the JNI C symbol name “Java_com_path_to_my_package_renderStuff” and finding FindClass () in “com / path / to / the / class” in your example. But since your stackoverflow is not an UnsatisfiedLinkageError, I can only guess that your provided example is not consistent with itself.

Using my example, I would expect the JNI C character name to be "Java_com_path_to_the_MyClass_renderStuff" and search for FindClass () on "com / path / to / the / MyClass". Using the uppercase first letter of the class and the lowercase name of the first letter of the method name can be important for binding purposes.

...

Are you sure the passed "jobj" is the same type as the "com / path / to / the / class" that you are viewing? Perhaps in your Java code you can wrap your native language:

 public void renderStuff() { if((this instanceof com.path.to.the.MyClass) == false) throw new RuntimeException("Unexpected class expected: com.path.to.the.MyClass"); renderStuff_internal(); } private native void renderStuff_internal(); 

What will provide this value in Java code without causing the JVM to crash. You will also need to adjust your C character name to add “_1internal” to the end by creating “Java_com_path_to_the_MyClass_renderStuff_1internal” (additional character “1” is required)

...

Maybe try checking for belt exclusions and braces between each expression you list about:

 if(env->ExceptionCheck()) { env->ExceptionDescribe(); env->ExceptionClear(); } 

This will perceive things as security breaches when trying to make a reflection when it may be prohibited.

...

  jclass cls = env->GetObjectClass(jobj); // instead of FindClass jmethodID mid = env->GetMethodID(cls, "showCar", "()V"); if(!mid) return; // whoops method does not exist env->CallVoidMethod(jobj, mid); 

Another idea is to remove the FindClass () call. This will work with any class GetMethodID worked on, sort of like dyhamic typing / late-binding.

+11
source share

All Articles