1. 程式人生 > >Java本地介面(JNI)程式設計指南和規範(第五章)

Java本地介面(JNI)程式設計指南和規範(第五章)

5.2.1 釋放區域性引用(Freeing Local References) 在大多數情況,當執行一個本地方法時,你不必擔心釋放區域性引用。當本地方法放回到呼叫者時,Java虛擬器為你釋放它們。然而,有些時候,你,"JNI"程式設計者,應該明確地釋放區域性引用為避免過分的記憶體使用。考慮一下下面的情況: .你需要建立大量的區域性引用在一個單獨的本地方法呼叫中。這可能導致"JNI"內部的區域性引用表的一個溢位。好的方法是適當地刪除些將不需要的區域性引用。例如,在下面程式片段中,原生代碼遍歷(iterate through)了一個潛在的大量的"string"陣列。每次迭代後,原生代碼應該明確釋放對字元元素的區域性引用,想下面: for ( i = 0 ; i < len ; i++){  jstring jstr = (*env)->GetObjectArrayElement(env, arr, i) ;  ...  (*env)->DeleteLocalRef(env, jstr) ; } .你需要寫個工具函式被從不清楚的上下文中呼叫。在4.3部分中顯示"MyNewString"例子說明"DeleteMyNewSring"使用為了刪除恰當區域性引用在一個工具函式中。否則,在"MyNewString"函式的每次呼叫後,兩個區域性引用將保持被分配。 .你的本地方法不再返回。例如,一個本地方法也可進入一個無終止的事件派遣迴圈。釋放在迴圈中建立的區域性引用至關重要(crucial),所以他們不會無限期的積累,導致記憶體洩漏。 .你本地方法訪問一個很大的物件,因此建立了一個這個物件區域性引用。然而本地方法在返回呼叫者前,執行額外的計算。即使物件在本地方法剩餘處不再本使用,這個很大物件的區域性引用將阻止垃圾蒐集這物件,直到本地方法返回。例如,在下面的程式片段中,因為事前,這有個清楚的"DeleteLocalRef"的呼叫,垃圾收集器可以釋放被"lref"指向的物件,在函式內部執行一個很長的計算時: JNIEXPORT void JNICALL Java_pkg_Cls_func(JNIEnv *env, jobject this ) {  lref = ...                     ...                            (*env)->DeleteLocalRef(env, lref) ;  lengthyComputation() ;           return ;                      }