2016-12-06 64 views
1

是JCLASS和jobject參考delete一個這樣正確的方式JNI deleteRef爲JCLASS和jobject

JNIEXPORT void JNICALL Java_method(JNIEnv *env,jobject, jobject objArray) 
{ 
    int n = env->GetArrayLength(objArray); 

    for (int i = 0; i<n ; ++i) 
    { 
     jobject sObject = env->GetObjectArrayElement(objArray, i); 
     jclass sObjectClass = env->GetObjectClass(sObject); 

     dosomething(sObjectClass, sObject); 

     env->DeleteLocalRef(sObject); 
     env->DeleteLocalRef(sObjectClass); 
    } 
+0

是的,對於本地引用,這是正確的。它應該防止參考表溢出。 – mkaes

+0

爲什麼你需要在循環裏面雖然'GetObjectClass'?你期望數組中的元素具有不同的類型嗎? – Michael

回答

1

簡短的回答:

是的,這是一個正確的做法。呼叫DeleteLocalRef不是必需的,但是如果objArray很大或者如果函數執行時間很長,則它非常有用。

較長的答案:

的Oracle參考文檔指出

基本類型,例如整數,字符等,複製Java和本機代碼之間 。任意Java對象,在另一手 手,通過引用傳遞。 VM必須跟蹤已傳遞給本機代碼的所有對象 ,以便這些對象不會被垃圾收集器釋放。本地代碼反過來必須 有辦法通知VM不再需要該對象。在 另外,垃圾收集器必須能夠移動由本地代碼引用的對象 。

因此,當本機代碼確實需要該對象時,本機代碼使用的任何對象都必須標記爲符合從本機代碼角度進行垃圾回收的條件。 JNI有兩種類型的引用 - 全局和本地引用。

所有Java對象通過JNI函數返回的是本地引用:因爲GetObjectArrayElementGetObjectClass檢索到的文獻是本地的。

VM自動釋放所有局部引用,當一個本地函數返回。所以在大多數情況下,沒有必要通過DeleteLocalRef釋放這些引用,因爲VM會自動釋放它們。

但是如果有一個函數調用需要大量的本地引用或通話時間長那麼就值得明確立即釋放他們並不需要它們時,不等待函數返回。釋放有助於虛擬機進行更好的內存管理。