如何解决JNI调用Java方法时出现的Bad global or local ref错误
问题分析与解决方案
首先,导致你遇到Bad global or local ref passed to JNI错误的核心原因是一个极易忽略的语法错误:在JNI代码的类引用判断逻辑里,你误用了赋值运算符而非比较运算符。
具体错误点
在你的本地方法实现中,这段代码存在致命问题:
jclass callingClass = env->GetObjectClass(classobj); if( callingClass = NULL ) // 这里是赋值=,不是比较== { cout << "Calling class null " << endl ; return ; } else cout << "calling class found" << endl ;
这里的callingClass = NULL是把NULL直接赋值给了callingClass,而非判断它是否为空。这会导致后续调用GetMethodID时传入一个空的类引用,直接触发JNI引用错误。
修复后的代码片段
把判断条件改成比较运算符==即可:
jclass callingClass = env->GetObjectClass(classobj); if( callingClass == NULL ) // 修正为== { cout << "Calling class null " << endl ; return ; } else cout << "calling class found" << endl ;
额外优化建议
结合日志里的警告,还有几个可以优化的点,避免后续出现其他JNI问题:
- 检查JNI调用异常:每次调用JNI函数(比如
GetObjectClass、GetMethodID)后,建议检查是否有异常抛出,防止错误扩散。例如:if (env->ExceptionCheck()) { env->ExceptionDescribe(); env->ExceptionClear(); return; } - 释放本地引用:JNI的本地引用有数量限制,日志里已经提示
JNI local refs: zu, exceeds capacity,所以用完jclass这类本地引用后,记得用env->DeleteLocalRef()释放,比如:jclass ListClass = env->GetObjectClass(listobj); // 使用完ListClass后 env->DeleteLocalRef(ListClass); - 确认方法签名正确性:虽然你的
indexToEs方法签名()V是正确的(无参数无返回值),但如果后续修改方法,要确保签名和Java方法完全匹配,可以用javap -s 类名命令生成准确的方法签名。
内容的提问来源于stack exchange,提问作者vignesh
相关产品推荐
相关产品推荐

