当调用CallVoidMethod时JNI崩溃

问题描述:

我试图从Android应用程序中的本机C代码调用java方法。这听起来很简单,但是在最终调用方法本身时,我的代码总是崩溃。 这里是我的代码: 本机C代码:当调用CallVoidMethod时JNI崩溃

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代码:

public void showCar(){  
    doSomething() 
} 

DoSomething的()甚至没有达到,我可以设置一个断点,这将永远不会被击中。如上所述,只要我注释掉CallVoidMethod调用,它就不会崩溃,但显然不会调用showCar()。任何提示?

+0

你确定'FindClass'和'GetMethodID'实际上返回非空结果吗? –

+0

是的,我们已经检查了两个结果,但似乎有二进制数据或其他东西。但它肯定不是空的。不幸的是,使用Android NDK和GDB调试本机代码变得相当困难,因为我们无法让C Debugger工作。 – Lennart

4的想法,为您提供:

...

JCLASS clazz中= env-> FindClass后面( “COM /路径/到/的/类”);

您可以确认名称不是“com/path/to/the/MyClass”,其中classname是大写第1个字符,显然名称“class”是保留字。在您的示例中,在“com/path/to/the/class”上使用JNI C符号名称“Java_com_path_to_my_package_renderStuff”和FindClass()查找之间存在细微差别。但由于你的stackoverflow不是一个关于UnsatisfiedLinkageError我只能猜测你提供的例子是不符合自己。

使用我的例子我期望JNI C符号名称为“Java_com_path_to_the_MyClass_renderStuff”,并在“com/path/to/the/MyClass”上查找FindClass()。对于连接目的,使用大写的第一个字母的类和方法名的第一个小写字母可能是重要的。

...

你确定了“jobj”传递是同类型的“COM /路径/到/的/类”您正在寻找呢?也许在你的Java代码中,你可以用你的本机包装:

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(); 

这将确保Java代码中的事情不会导致JVM崩溃。您还需要调整你的C符号名称追加了“_1internal”到年底制定“Java_com_path_to_the_MyClass_renderStuff_1internal”(额外的“1”字意)

...

也许尝试带和背带例外在你列出的每条语句之间进行检查:

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

这会在不允许的情况下尝试进行反射时发现安全违规事件。

...

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); 

另一个想法去除的findClass()调用。这可以与GetMethodID的任何类一起工作,类似于dyhamic类型/后期绑定。

+0

使用GetObjectClass()而不是FindClass是我需要知道的。 – Alyoshak