Android JNI開發摘錄(五)之對象引用處理

六.本機代碼中的對象引用

     終於講到對象引用了,在此推薦JNI開發必看的

使用 Java Native Interface 的最佳實踐

    JNI提供了函數集來使用本機代碼中的Java對象,包括前面已經介紹了的串、數組和一般對象。那麼,JNI到對象的引用是如何被處理的呢?更確切一些,垃圾收集程序是如何處理對象引用,並且知道什麼時候收集垃圾對象呢?JNI提供了3種不同的引用類型:

    本地引用:(Local Reference)只用在一個單一本機方法中。

    全局引用:(Global Reference)在本機方法的多次調用之間使用。

    弱全局引用:(Weak Global Reference)同全局引用一樣,但是該類型引用無法組織對象實施垃圾收集。

    1.本地引用:

     本地引用是通過使用NewLocalRef函數來顯式創建的,儘管許多JNI函數都會返回一個本地引用,這些引用都只是用於本機方法執行期間,在本機函數返回時消失。本地引用不應該在本機端被緩存(例如在一個本地靜態變量中被保存),因爲他們不能用在本機方法的多次調用中。只要本機函數返回,任意存在的本地引用都會被進行垃圾收集。如果希望函數返回之前回收本地引用,可以使用DeleteLocalRef函數來顯式回收本地引用。本地引用只在創建他們的線程中有效,因此不要試圖存儲一個本地引用並在另一條線程中使用。

     顯式創建本地引用:

jobject NewLocalRef(jobject ref);


     顯式釋放本地引用:

void DeleteLocalRef(jobject obj);



    2.管理本地引用

    有必要知道當前有多少本地引用被使用,因爲許多函數都返回本地引用。JNI需要設置本地引用的最大值。同時,如果創建了大對象的引用,就有耗盡可用存儲器的風險。下面的函數用於本地引用的管理:  




/*該函數確保至少可以按照最小值創建本地引用。VM則確保當一個本機方法被調用時,至少有16個本地引用可以被創建。如果試圖創建超過可用數量的更多本地引用,將會調用一個FatalError。該函數如果調用成功,則返回零;如果拋出一個OutOfMemoryException,則返回一個負值。*/

jint EnsureLocalCapacity(jint capacity);
/* PushLocalFrame是一個創建本地引用新作用域的有用函數,這使得PushLocalFrame函數可以釋放其使用的框架中所有已分配的本地引用。當該函數被調用時,本地引用的最低數量將在本框架中被創建。該函數如果執行成功則返回0,如果由於錯誤拋出一個OutOfMemoryException,則返回一個負值。*/

 jint PushLocalFrame(jint capacity);



/*PopLocalFrame函數釋放當前框架中的所有本地引用(彈出一個框架)。因爲存儲該函數的結果(返回值)可能會導致在即將被彈出的框架中創建一個本地引用,該函數接收一個可以導致引用在當前框架被彈出之後的最高框架中創建的參數。這就確保可以維護一個存儲PopLocalFrame函數結果的引用。*/

 jobject PopLocalFrame(jobject result);


     3.全局引用和弱全局引用

     全局引用在一個本機方法的多次不同調用之間使用。他們只能通過使用NewGlobalRef函數來創建。全局引用可以在幾個線程之間使用。全局引用提供了諸多好處。但是有一個小問題:Java無法控制全局引用的生命週期。用戶必須自行判斷全局引用何時不再需要,同時使用DeleteGlobalRef來釋放他。弱全局引用與全局引用十分類似,但是其基本對象可以在任何時候進行垃圾收集。JNI提供一個IsSameObject的特定調用來找出基本對象是否仍然有效。

      1)創建全局引用和弱全局引用:

/* NewGlobalRef創建一個新的全局引用,並且返回該引用。NewWeakGlobalRef創建並返回一個弱全局引用。它們的參數就是要創建對象的類。如果沒有一個到類的句柄,可以通過FindClass來獲得一個類。如果試圖創建到空對象的引用,或者對象無法被創建,將返回NULL。如果由於沒有可用存儲器而使得引用無法被創建,則拋出一個OutOfMemoryException。*/

jobject NewGlobalRef(jobject lobj);

jweak NewWeakGlobalRef(jobject obj);


     2)刪除全局和弱全局引用

void DeleteGlobalRef(jobject gref);

void DeleteWeakGlobalRef(jweak ref);


      4.引用比較

      JNI提供一個特定函數,IsSameObject,用於測試在兩個引用之後的對象是否相同。對於C++來說,關鍵字NULL對應於Java中的一個空對象。這樣,就可以將NULL作爲一個參數傳入IsSameObject或者直接將一個對象引用同NULL比較。

/* 如果對象是相同的,返回JNI_TRUE,否則返回JNI_FALSE。如果試圖使用IsSameObject來對一個弱全局引用同NULL作比較,如果基本對象沒被垃圾收集,則返回JNI_TRUE,否則返回JNI_FALSE。*/

jboolean IsSameObject(jobject obj1,jobject obj2);


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章