java - 使用 NewGlobalRef 时的 JNI "local reference table overflow"

标签 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 时,我收到错误“本地引用表溢出”,但如果我不这样做按如下方式使用 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/

相关文章:

android - 从 Spannable 获取第一个 Span

android - 应用程序启动时以编程方式调用 rawQuery

c++ - 如何使用Qt Creator调试C++项目?

java - 如何将 jpanel 与油漆一起使用(或重新油漆)

java - 如何使用 Spring Data Rest 和 PagingAndSortingRepository 处理异常?

java - 使用 greenDAO 实现接口(interface)时出错

c++ - ASSERT-C++ 的编译器错误

java - 无法将 Google map V3 与 GWT 一起使用

java - 错误 : class MapPane is public, 应在名为 MapPane.java 的文件中声明

c++ - 在 C++ 中,可以重命名/别名非命名空间、非类名吗?