安卓 cronet 庫 JNI ERROR (app bug): local reference table overflow (max=512)

1、問題背景

由於定位問題需要,將 cronet 庫中 quic 部分的 LOG_LEVEL 爲 -3 級別的日誌一併通過回調函數輸出了,

但導致了 cronet 庫的崩潰,崩潰的直接原因是輸出日誌過多,導致了 jni 層的局部引用表溢出。

那麼肯定是代碼中使用局部引用的次數過多、過頻繁,並且未及時釋放這些局部引用,從而導致了崩潰。

2、問題定位、解決

  • 2.1 問題分析
    首先需要了解什麼樣的局部引用會導致這樣的問題,以及這些局部引用如何釋放,以及合適的釋放時間點
    局部引用包括 FindClass 返回的對象引用,NewXXX 等方法返回的對象,如果通過 return 返回到 Java 層,
    或者通過 CallVoidMethod 等方法傳遞到了 Java 層,則在 C++ 層不需要釋放它們,否則需要手動釋放這些對象,

  • 2.2 問題代碼定位
    代碼中,下面這段代碼中的 callback_class 變量並未被後續使用,且爲通過某個方法傳遞到 Java 層,
    且未手動釋放,可能造成了對象局部引用溢出。

jclass callback_class = handleInstance->getCallbackClass();
if (callback_class == NULL || callback_class == 0) {
    LOGW("From cache class Unable to find");
}

該部分代碼未在後續代碼中使用,因此可以直接刪除,重新編譯 cronet 提交測試發現仍然崩潰,

繼續分析代碼,有兩處 new 了 string 對象:

jstring logString = env->NewStringUTF(str.c_str());


env->CallVoidMethod(callback.obj(), callback_fun, severity, fileString,
                        jMsgStart, logString);

後續並未刪除 logString,因此可以增加代碼,刪除這些引用:

env->DeleteLocalRef(logString);

重新打包測試,崩潰未再出現。

參考鏈接

JNI error : Local reference table overflow 512 entries
JNI內存泄露處理方法彙總

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章