2012-08-23 60 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,但它現在工作,所以我現在與它生活:)