最近又在开发JNI相关的项目了。原本一切正常,坐等测试完毕发布版本,然而理想是美好的,现实是骨感的。测试跑过来跟我说在测异常流程(开发人员听到估计就头疼)的时候发生了闪退问题。我赶忙拿过来本身测,果真复现了,日志中显示local reference table overflow (max=512)
。嗯?JNI中出现了内存泄漏?但是我已经按照网上的例子把全部该释放的对象都释放了啊,怎么回事啊?java
先来看下有哪些要释放的:数组
FindClassbash
jclass ref= (env)->FindClass("java/lang/String");
env->DeleteLocalRef(ref);
复制代码
NewString/ NewStringUTF/NewObject/NewByteArray测试
// 建立 jstring 和 char*
jstring jstr = (*jniEnv)->CallObjectMethod(jniEnv, test1, test2);
char* cstr = (char*) (*jniEnv)->GetStringUTFChars(jniEnv,jstr, 0);
// 释放
(*jniEnv)->ReleaseStringUTFChars(jniEnv, jstr, cstr);
(*jniEnv)->DeleteLocalRef(jniEnv, jstr);
复制代码
GetObjectField/GetObjectClass/GetObjectArrayElementui
jclass ref = env->GetObjectClass(robj);
env->DeleteLocalRef(ref);
复制代码
GetByteArrayElementsspa
jbyte* array= (*env)->GetByteArrayElements(env,jarray,&isCopy);
(*env)->ReleaseByteArrayElements(env,jarray,array,0);
复制代码
NewGlobalRef/DeleteGlobalRef日志
jobject ref= env->NewGlobalRef(customObj);
env->DeleteGlobalRef(customObj);
复制代码
开始了苦逼的代码检查之路,找了许久,考虑各类可能的缘由,而后各类测试,仍是会在异常流程中出现闪退,使人绝望。code
最后,突然看到了这个:对象
jbyteArray arr = (jbyteArray) (*env)->CallObjectMethod(env, local_object, methodID, java_slot,jbyteArray1);
复制代码
从JNI中反射调用Java层方法,返回了一个字节数组,我去。。。,没有删除这个对象,这个数组在异常流程中被不断建立,而且没有获得回收,因此很快就出现了local reference table overflow (max=512)
错误。找到问题根源了,赶忙检查代码,全部相似的接口所有进行修改。接口
(*env)->DeleteLocalRef(env, arr);
复制代码
而后再次送测,终于没有问题了。
由于这个,要解决只要一行代码的问题,花费了我大半个下午时间,因此在这里记录一下,提醒本身,之后记得释放全部在Native层中建立的本地对象!