JNI“本地参考表溢出"使用NewGlobalRef时 [英] JNI "local reference table overflow" when using NewGlobalRef

查看:65
本文介绍了JNI“本地参考表溢出"使用NewGlobalRef时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个使用JNI的应用程序,但是在使用全局引用时出现本地引用表溢出"错误:

I'm developing an app that uses JNI but I'm getting a "local reference table overflow" error when using global references:

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 如下,我不会崩溃:

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:

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 返回您正在创建的本地引用(这意味着该本地引用将被添加到当前线程的本地引用表).

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).

除非您返回java或从VM分离本机线程,否则不会清除该引用表.而且,如果您继续创建本地引用而不清除本地引用表,那么最终将耗尽表中的可用条目.

Unless you return back to java or detach the native thread from the VM, that reference table isn't going to be cleared. 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.

全局引用的要点是,当您返回java或分离当前线程时,它们不会被自动删除,因此以后可以使用相同的引用.但是,在您的情况下,您似乎并不需要它,尽管您的示例看起来有些虚构(您创建了从未使用过的对象).

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. 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).

这篇关于JNI“本地参考表溢出"使用NewGlobalRef时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆