Context
JNI创建的reference太多,导致崩溃。具体查找 jString, jclass, jobject
简要分析
什么是Local reference
Every argument passed to a native method, and almost every object returned by a JNI function is a “local reference”.
This applies to all sub-classes of jobject, including jclass, jstring, and jarray (类型)
- native 方法的参数
JNIEXPORT jlong JNICALL Java_com_TestClass_testMethod(JNIEnv *env, jobject obj, jstring path1, jstring path2, jstring path3, jstring path4)
方法参数列表中的 jstring jobject
- JNI方法的返回值(绝大部分)
const char *str_path1 = env->GetStringUTFChars(path1, 0);
env->ReleaseStringUTFChars(path1, str_path1);
什么是JNI方法
JNIEnv指向的方法,也就是 env->方法
,当然C和C++调用方式不同
什么是JNIEnv
指向JNI函数表的接口指针(也就是指向 JNI方法表的指针,所以env->function, function是JNI函数就很明白了)
还有什么reference
还有NewGlobalRef、NewWeakGlobalRef
与localReference区别
localReference只作用于当前的方法:
jobject obj对应的java对象 TestClass testObj, 即使 testObj 在native方法调用后仍旧存在,在native方法后调用 obj也是失败的。
jclass localClass = env->FindClass("MyClass");
jclass globalClass = reinterpret_cast<jclass>(env->NewGlobalRef(localClass));
NewGlobalRef
显然就是全局的引用,允许testObj的作用于超出方法。也是GC root的知识点(垃圾回收)。
NewWeakGlobalRef
相当于java的weak reference,不妨碍 java gc testObj。所以NewWeakGlobalRef引用的java对象有可能为null,所以需要判断
(*env)->IsSameObject(env, obj, null)
reference不同通过==来判断,引用的是否为相同的java对象,需要上述IsSameObject
判断
LocalReference多少是多
java文档保证最低16个,我的bug是Android7.1.1手机,日志显示localReference最多512个。是for循环里创建string忘了回收
解决
env->SetObjectArrayElement(results,i,env->NewStringUTF(json_results[i].c_str()));
改为
jstring elem = env->NewStringUTF(json_results[i].c_str());
env->SetObjectArrayElement(results,i,elem);
env->DeleteLocalRef(elem);
都需要回收吗?
JNIEXPORT jstring JNICALL Java_com_sogou_ocr_OcrRecog_nativeGetVersion(JNIEnv *env, jclass cls)
{
return env->NewStringUTF(SDKVERSION);
}
这种return的你怎么回收。
you should free them manually with DeleteLocalRef instead of letting JNI do it for you.
也就是说JNI会自己回收,你只要别频繁超出就行。
总结
local reference系统会回收,但频繁创建需要自己回收(系统没来及)