2012-08-23 53 views
5

后,当我运行代码,我得到一个错误“无法加入到JNI本地参考表有512项”JNI表溢出甚至deleteLocalRef

这是我的代码:

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

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

pJNIEnv->DeleteLocalRef(pJNIData); 

我已阅读几个建议,但他们都没有工作!尽管DeleteLocalRef,它无法正常工作。该函数用于一个简单地调用所有函数的探查器...

+0

你确定这是代码填满你的ref表吗?当你使用一个常量硬编码的pJNIData时问题会消失吗? –

+0

@vtmarvin不确定。这是否对参考表有所不同? - > JNIEnv * pJNIEnv = profilerGetJNIEnv(); 如果(pJNIEnv!) \t \t { \t \t \t LOGE( “探查ERROR:Java环境缺失(空)”); \t \t \t return; \t \t} –

回答

2

我看到这个时,一个JNI方法调用Java代码(在我的情况下,该方法不是静态的)。据我所知,当从JNI(我的意思是,直到顶层JNI函数返回)调用Java方法时,未使用的本地引用是而不是自动删除。

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虚拟机Dalvik的文档/文件/ JNI的tips.html请与下方找到“本地与全球参考”)

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

0

我以为我会芯片以防万一遇到这个问题。这是一个奇怪的案例,让我困惑了好几个小时!

好的,我有一个NDK应用程序,被调用的Java代码是在运行时加载的apk里面。我不知道运行时加载是否会以任何方式影响,但我想我应该提及它。

现在在一个C++方法中,我使用find类和getmethodid将构造函数获取到HashMap并调用它来获取新的HashMap实例。然后我使用jni调用从C++端填充HashMap。到现在为止还挺好。 然后,我将HashMap传递给java代码,并且所有工作都按预期工作。一旦Java代码返回,我就在HashMap上调用DeleteLocalRef。没有错误被抛出,但参考未被删除。

当我最终运行512个本地引用(从多次调用此函数)并且错误转储显示localref存储区中的最后10个项目几乎都是HashMap时,才会出现这种情况。我会明白,GC不会在方法结束时收集这些引用,因为我正在制作一个多线程的ndk应用程序。然而,DeleteLocalRef应该已经工作。

解决方法: 在我发现,创建从JNI调用Java方法我写HashMap中是很好,和基准然后free'able结束。有一个java函数似乎很疯狂,它实际上只是返回一个新的HashMap,但它现在工作,所以我现在与它生活:)