我正在开发一个使用 JNI 的应用程序,但在使用全局引用时遇到“本地引用表溢出”错误:
art/runtime/indirect_reference_table.cc:115] JNI ERROR (app bug): local reference table overflow (max=512)
art/runtime/indirect_reference_table.cc:115] local reference table dump:
art/runtime/indirect_reference_table.cc:115] Last 10 entries (of 508):
art/runtime/indirect_reference_table.cc:115] 507: 0x13f08b80 com.company.util.jni.JniCompanyHelper$HTTPStream
art/runtime/indirect_reference_table.cc:115] 506: 0x13ef5520 com.company.util.jni.JniCompanyHelper$HTTPStream
art/runtime/indirect_reference_table.cc:115] 505: 0x13eb4a80 com.company.util.jni.JniCompanyHelper$HTTPStream
代码如下:
class Foo {
public:
Foo(){}
void doSomething(){
JNIEnv* env = getEnv();
javaObject = env->NewGlobalRef(env->CallStaticObjectMethod(...));
}
~Foo() {
JNIEnv* env = getEnv();
env->DeleteGlobalRef(javaObject);
}
private:
jobject javaObject;
};
// ...
// Run the loop in a separate thread
for(int i =0; i< 1000; i++) {
Foo foo;
foo.doSomething();
}
当我创建一个大循环来创建和销毁 1000 个 Foo
实例并运行 doSomething
时,我收到错误“本地引用表溢出”,但如果我不这样做按如下方式使用 NewGlobalRef
,我没有遇到任何崩溃:
class Foo {
public:
Foo(){}
void doSomething(){
JNIEnv* env = getEnv();
jobject javaObject = env->CallStaticObjectMethod(...);
env->DeleteLocalRef(javaObject);
}
~Foo() {
}
};
有人知道我在这里缺少什么吗?
最佳答案
CallStaticObjectMethod
返回对您正在创建的任何内容的本地引用(这意味着本地引用将添加到当前线程的本地引用表中)。
除非您返回到 java 或将 native 线程与虚拟机分离,否则该引用表不会被清除。如果您继续创建本地引用而不清除本地引用表,您最终将耗尽表中的可用条目。
您的固定版本通过在使用完每个本地引用后立即删除它来解决此问题。
全局引用的要点是,当您返回 java 或分离当前线程时,它们不会自动删除,因此您可以稍后使用相同的引用。但在你的情况下,你似乎不需要它,尽管你的例子看起来有点做作(你创建了你从不使用的对象)。
关于java - 使用 NewGlobalRef 时的 JNI "local reference table overflow",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47019893/