简体   繁体   English

使用 NewGlobalRef 时的 JNI“本地引用表溢出”

[英]JNI "local reference table overflow" when using NewGlobalRef

I'm developing an app that uses JNI but I'm getting a "local reference table overflow" error when using global references:我正在开发一个使用 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

The code goes as follows:代码如下:

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();
}

When I create a big loop that creates and destroy 1000 Foo instances and run doSomething , I get the error "local reference table overflow" but if I don't use NewGlobalRef as follows, I do not get any crash:当我创建一个创建和销毁 1000 个Foo实例并运行doSomething的大循环时,我收到错误“本地引用表溢出”,但如果我不使用NewGlobalRef如下,我不会遇到任何崩溃:

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

Anybody knows what I'm missing here?有人知道我在这里想念什么吗?

CallStaticObjectMethod returns a local reference to whatever it is you're creating (which implies that the local reference will be added to the current thread's local reference table). CallStaticObjectMethod返回对您正在创建的任何内容的本地引用(这意味着本地引用将添加到当前线程的本地引用表中)。

Unless you return back to java or detach the native thread from the VM, that reference table isn't going to be cleared.除非您返回 java 或从 VM 分离本机线程,否则不会清除该引用表。 And if you keep creating local references without clearing the local reference tables, you're eventually going to run out of free entries in the table.如果您继续创建本地引用而不清除本地引用表,您最终将耗尽表中的可用条目。

Your fixed version takes care of this by deleting each local reference immediately after you're done using it.您的固定版本通过在您使用完后立即删除每个本地引用来处理此问题。

The point of global references is that they won't be automatically deleted when you return back to java or detach the current thread, so you can use that same reference later on.全局引用的要点是当您返回 java 或分离当前线程时它们不会被自动删除,因此您可以稍后使用相同的引用。 But in your case you don't seem to need that, although your example looks a bit contrived (you create objects that you never use).但是在您的情况下,您似乎不需要那个,尽管您的示例看起来有点做作(您创建了从未使用过的对象)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM