6

当我运行代码时,我收到一个错误“添加到 JNI 本地引用表失败有 512 个条目”

这是我的代码:

jstring pJNIData = pJNIEnv->NewStringUTF ( variables[0].GetStringValue() );

pJNIEnv->CallStaticVoidMethod ( pJNIActivityClass, pJNIMethodIDStartTime, pJNIData ) ;

pJNIEnv->DeleteLocalRef(pJNIData);

我已经阅读了几个建议,但没有一个有效!尽管有DeleteLocalRef,但它无法正常工作。该函数用于一个探查器,它从字面上调用所有函数......

4

2 回答 2

2

当一个名为 Java 代码的 JNI 方法(在我的例子中,该方法不是静态的)时,我已经看到了这一点。据我了解,当从 JNI 调用 Java 方法时,未使用的本地引用不会自动删除(我的意思是,直到顶级 JNI 函数返回)。

IIRC 要么已经在日志中有关于内存对象的信息,要么我可以添加一些日志记录;从这些信息中,我发现了我之前没有提到的垃圾项目。它们是两个数组和一个类,在随后的调用中创建,但没有被垃圾回收。

// in a function that calls a Java method from JNI
jbyteArray srcArray = env->NewByteArray(len);
jclass cls = env->FindClass("com/something/MyClass");
jmethodID mid = env->GetMethodID(cls, "mymethod", "([BI)[B");
jbyteArray resArray = (jbyteArray)env->CallObjectMethod(obj, mid, srcArray, XXXX);

...
env->DeleteLocalRef(cls);
env->DeleteLocalRef(resArray);
env->DeleteLocalRef(srcArray);
// no need to do anything with mid

请注意,尽管这三个本地参考的获得方式不同,但它们都在附近徘徊。

有用的链接: http: //www.netmite.com/android/mydroid/dalvik/docs/jni-tips.html#local_vs_global_references (或找到 Dalvik VM 文档 dalvik/docs/jni-tips.html 并找到“本地与全球参考”)

JNI 返回的每个对象都是“本地引用”。这意味着它在当前线程中的当前本机方法的持续时间内有效。即使对象本身在本机方法返回后继续存在,引用也是无效的。这适用于 jobject 的所有子类,包括 jclass 和 jarray。[...] 注意:方法和字段 ID 只是 32 位标识符,不是对象引用,不应传递给 NewGlobalRef。GetStringUTFChars 和 GetByteArrayElements 等函数返回的原始数据指针也不是对象。

于 2012-12-24T12:01:04.530 回答
0

I thought I would chip in just in case anyone else runs into this issue. This is a weird case that kept me confused for hours!

Ok so I have an NDK app and the Java code being called is inside an apk that is loaded at runtime. I have no idea if the runtime loading effects this in any way but I thought I should mention it.

Now in a c++ method I use find class and getmethodid to get the constuctor to a HashMap and call it to get a new HashMap instance. I then populate the HashMap from the c++ side using jni calls. So far so good. I then pass the HashMap to java code and, again, all is working as expected. Once the java code has returned I call DeleteLocalRef on the HashMap. No errors are thrown but the reference is not deleted.

This only came up when I finally ran over 512 local references (from multiple calls to this function) and the error dump showed that the last 10 items in the localref store were nearly all HashMaps. I would understand that the GC would not collect these references at the end of the method as I am make a multithreaded ndk app. However the DeleteLocalRef should have worked.

The Fix: In the end I found that creating the HashMap from a jni call to a java method I wrote was fine, and the reference was then free'able. It seems crazy to have a java function that literally just returns a new HashMap but it worked so for now I am living with it :)

于 2014-05-26T22:29:41.520 回答