JNI DETECTED ERROR IN APPLICATION

Java结合C++遇JNI错误,重启VMware恢复

DETECTED ERROR IN APPLICATION: JNI GetMethodID called with pending exception java.lang.NoSuchMethodError: no non-static method

vmware环境安装ubuntu,android studio调试,java 结合 c++ 读取检测模型,代码一直正常,突然JNI DETECTED ERROR,查看接口及相关代码,无任何变化。

重启vmware,正常

<think> 根据用户需求,用户遇到JNI错误:'use of deleted local reference 0x89'。这个错误通常与JNI局部引用管理有关。以下将逐步解释原因并提供解决方案。 ### 错误原因 在JNI中,局部引用(Local Reference)由JNI函数创建(如`NewObject`、`NewString`等),并在当前本地方法执行期间有效。当本地方法返回时,局部引用会自动释放。然而,在以下情况下可能引发该错误: 1. **手动删除后再次使用**:调用`DeleteLocalRef`删除一个局部引用后,再次使用该引用。 2. **超出作用域后使用**:局部引用在创建它的本地方法返回后自动失效,若在另一个方法中使用该引用则会导致错误。 3. **局部引用表溢出**:创建过多局部引用未及时删除,导致局部引用表溢出(默认容量为512),此时JVM可能自动删除部分引用。 ### 解决方案 #### 1. **避免使用已删除的引用** - 确保在调用`DeleteLocalRef`后不再使用该引用。 - 示例: ```c jobject localObj = env->NewObject(...); // 创建局部引用 // 使用localObj... env->DeleteLocalRef(localObj); // 删除引用 // 之后不再使用localObj ``` #### 2. **管理局部引用生命周期** - 若需在多个本地方法间传递对象,应使用**全局引用**(Global Reference): ```c jobject globalObj = env->NewGlobalRef(localObj); // 转换为全局引用 env->DeleteLocalRef(localObj); // 删除局部引用 // 后续可通过globalObj使用对象 ``` - 使用后务必释放全局引用: ```c env->DeleteGlobalRef(globalObj); ``` #### 3. **处理局部引用表溢出** - **显式删除不再使用的局部引用**:尤其在循环中创建大量引用时。 ```c for (int i = 0; i < 1000; i++) { jobject tmp = env->NewObject(...); // 使用tmp... env->DeleteLocalRef(tmp); // 及时删除 } ``` - **扩大局部引用表容量**(谨慎使用):通过`PushLocalFrame`和`PopLocalFrame`管理批量引用: ```c env->PushLocalFrame(256); // 创建容量为256的新帧 jobject ref1 = env->NewObject(...); // 在新帧中创建引用 jobject ref2 = env->NewObject(...); // 使用ref1、ref2... env->PopLocalFrame(NULL); // 释放整个帧及其所有引用 ``` #### 4. **使用`EnsureLocalCapacity`预分配** - 提前检查局部引用表容量: ```c if (env->EnsureLocalCapacity(100) == JNI_OK) { // 安全创建100个局部引用 } else { // 处理错误 } ``` ### 调试建议 - **启用JNI检查**:在Android开发中,通过`adb shell setprop debug.checkjni 1`开启额外检查。 - **使用CheckJNI模式**:捕获无效引用使用等错误,帮助定位问题。 ### 总结 该错误的核心是**无效引用访问**,解决方案围绕: 1. 避免使用已删除的引用; 2. 跨方法传递时升级为全局引用; 3. 及时删除局部引用防止溢出。 §§相关问题§§ 1. JNI中局部引用和全局引用的区别是什么? 2. 如何避免JNI中的内存泄漏? 3. JNI常见错误有哪些及如何调试? </think> ### JNI中 "use of deleted local reference 0x89" 错误解决方案 这个错误表示你正在尝试使用一个已被删除的JNI局部引用。以下是系统性的解决方法: #### 1. **理解引用生命周期** - 局部引用在本地方法返回时**自动删除** - 若手动调用`DeleteLocalRef()`后继续使用引用会导致此错误 - 示例错误代码: ```c jobject obj = env->NewObject(...); // 创建引用 env->DeleteLocalRef(obj); // 删除引用 env->CallVoidMethod(obj, ...); // 错误!使用已删除引用 ``` #### 2. **关键解决方案** **✅ 方案1:避免重复删除** ```c jobject localRef = env->NewObject(...); // 使用引用... // 不要重复删除!下列代码仅在特定情况需要: // env->DeleteLocalRef(localRef); ``` **✅ 方案2:跨线程/函数时升级为全局引用** ```c // 创建全局引用 jobject globalRef = env->NewGlobalRef(localRef); env->DeleteLocalRef(localRef); // 删除局部引用 // 在其他函数/线程中使用全局引用 env->CallVoidMethod(globalRef, ...); // 最后必须手动释放 env->DeleteGlobalRef(globalRef); ``` **✅ 方案3:使用`Push/PopLocalFrame`管理批量引用** ```c env->PushLocalFrame(64); // 创建新引用作用域 jobject ref1 = env->NewObject(...); // 自动管理 jobject ref2 = env->NewObject(...); // 自动释放所有当前帧内的引用 env->PopLocalFrame(NULL); ``` #### 3. **预防措施** - **引用计数检查**:使用Android Studio的**Memory Profiler**检查JNI引用泄漏 - **启用严格模式**:在`AndroidManifest.xml`中添加: ```xml <application android:debuggable="true" ...> ``` - **JNI日志**:通过`adb shell setprop log.tag.JNIREF VERBOSE`开启引用日志 #### 4. **典型错误场景修复** **场景:在循环中创建引用未释放** ```c for (int i = 0; i < 1000; i++) { jstring jstr = env->NewStringUTF("test"); // 处理jstr... env->DeleteLocalRef(jstr); // 必须显式删除! } ``` **场景:跨线程使用引用** ```c // 错误做法:直接传递局部引用 std::thread th([=]{ env->CallVoidMethod(localRef, ...); // 崩溃! }); // 正确做法:使用全局引用 jobject globalRef = env->NewGlobalRef(localRef); std::thread th([=]{ env->CallVoidMethod(globalRef, ...); env->DeleteGlobalRef(globalRef); // 在线程内释放 }); ``` > **重要原则**:局部引用生命周期不超过当前本地方法调用,若需长期持有必须转换为全局引用。在Android开发中,超过98%的此类错误源于跨线程使用局部引用或手动删除后复用[^1]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值