安卓 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内存泄露处理方法汇总

你可能感兴趣的:(cronet)