JNI"本地参考表溢出"何时使用NewGlobalRef

时间:2017-10-30 16:19:25

标签: java android c++ java-native-interface

我正在开发一个使用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的大循环时,我得到错误&#34;本地参考表溢出&#34;但是,如果我不按照以下方式使用NewGlobalRef,我不会发生任何崩溃:

class Foo {
public:
    Foo(){}
    void doSomething(){
        JNIEnv* env = getEnv();
        jobject javaObject = env->CallStaticObjectMethod(...);
        env->DeleteLocalRef(javaObject);
    }
    ~Foo() {
    }
};

有人知道我在这里失踪了吗?

1 个答案:

答案 0 :(得分:0)

CallStaticObjectMethod返回对您正在创建的内容的本地引用(这意味着本地引用将添加到当前线程的本地引用表中)。

除非您返回java或从VM分离本机线程,否则该引用表将不会被清除。如果您在不清除本地参考表的情况下继续创建本地引用,那么您最终将会耗尽表中的空闲条目。

您的固定版本通过在您完成使用后立即删除每个本地参考来解决此问题。

全局引用的要点是,当您返回到java或分离当前线程时,它们不会被自动删除,因此您可以稍后使用相同的引用。但是在你的情况下,你似乎并不需要这样,虽然你的例子看起来有点做作(你创建了你从未使用过的对象)。