最近又在開發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層中建立的本地對象!