调用返回jstring的GetObjectField后是否需要对jstring执行DeleteLocalRef
关于GetObjectField返回jstring是否需要调用DeleteLocalRef的解答
核心结论
需要调用,jstring类型和普通JNI对象的局部引用管理规则完全一致
具体原因说明
- JNI类型中
jstring本质对应Java层的java.lang.String对象,不属于jint/jboolean这类无需引用管理的基础数据类型,所有JNI接口返回的对象类型引用(包括jstring、jclass、jarray、jobject等)只要属于局部引用范畴,都需要主动释放避免局部引用表溢出。 GetObjectField接口返回的是jobject类型的局部引用,你将其强转为jstring的操作仅属于类型标识转换,不会改变它作为局部引用的性质,因此和普通对象的局部引用处理规则没有区别。- 仅有一种场景可以省略手动释放:Native方法执行结束后JVM会自动清空当前线程的所有局部引用,若你获取的
jstring仅在方法内短生命周期使用、且不会出现大量引用堆积的情况,省略释放不会立刻触发问题,但仍然推荐遵循规范手动释放,避免后续逻辑迭代后引入溢出风险。
正确代码示例
// 假设已经获取到env、目标对象obj、String类型的属性ID field_id jstring java_str = (jstring)(*env)->GetObjectField(env, obj, field_id); if (java_str == NULL) { // 空指针处理逻辑,此处也要注意不要漏释放(如果前面还有其他局部引用的话) return; } // 读取字符串内容到Native侧 const char* c_str = (*env)->GetStringUTFChars(env, java_str, NULL); // ...... 此处为使用c_str的业务逻辑 ...... // 释放字符串内容占用 (*env)->ReleaseStringUTFChars(env, java_str, c_str); // 释放jstring对应的局部引用 (*env)->DeleteLocalRef(env, java_str);
注意:
ReleaseStringUTFChars/ReleaseStringChars和DeleteLocalRef的作用完全独立:前者用于释放Native侧获取的字符串内容内存,后者用于释放JNI局部引用表的占位,两者不可互相替代,都需要按顺序执行。
内容的提问来源于stack exchange,提问作者API_1024
相关产品推荐
相关产品推荐

