Android JNI編程提高篇之二

來源:互聯網
上載者:User
文章目錄
  • 全域引用
  • 弱全域引用

上文《Android JNI編程提高篇之一》中我和大家分享了局部引用的一些理解,本文我將繼續和大家全域引用和弱全域引用的一些理解。這也可以作為我學習《Java Native Interface: Programmer’s Guide and Specification》一個總結,歡迎大家對本文的理解拍磚。

全域引用

    在所有引用中,我覺得全域引用是最好理解的一個了。為什麼呢?主要和C語言的全域變數非常相近。

    上文《Android JNI編程提高篇之一》我已經提到局部引用大部分是通過JNI API返回而建立的,而全域引用必須要在Native代碼中顯示的調用JNI API NewGlobalRef來建立,建立之後將一直有效,直到顯示的調用DeleteGlobalRef來刪除這個全域引用。請注意NewGlobalRef的第二個參數,既可以用一個局部引用,也可以用全域引用產生一個全域引用,當然也可以用弱全域引用產生一個全域引用,但是這中情況有特殊的用途,後文會介紹。

    全域引用和局部引用一樣,可以防止其指向的對象被Java虛擬機器記憶體回收。與局部引用只在當前線程有效不同的是全域引用可以在多線程之間共用(如果是多線程編程需要注意同步問題)。

弱全域引用

    弱全域引用是非常讓人迷惑的一個,主要是它的用法太怪異了。

    弱全域引用和全域引用一樣,需要顯示的建立和銷毀。建立調用NewWeakGlobalRef,銷毀調用DeleteWeakGlobalRef。

    與全域引用和局部引用能夠阻止Java虛擬機器記憶體回收其指向的對象不同,弱全域引用指向的對象隨時都可以被Java虛擬機器記憶體回收,所以使用弱全域變數的時候,要時刻記著:它所指向的對象可能已經被記憶體回收了。JNI API提供了引用比較函數IsSameObject,用弱全域引用和NULL進行比較,如果返回JNI_TRUE,則說明弱全域引用指向的對象已經被釋放。需要重新初始化弱全域引用。根據上面的介紹你可能會寫出如下的代碼:

static jobject weak_global_ref = NULL;if((*env)->IsSameObject(env, weak_global_ref, NULL) == JNI_TRUE){    /* Init week global referrence again */    weak_global_ref = NewWeakGlobalRef(...);}/* Process weak_global_ref */.....

    上面這段代碼錶面上沒有什麼錯誤,但是我們忘了一點兒,Java虛擬機器的記憶體回收隨時都可能發生。假設如下情形:

1、通過引用比較函數IsSameObject判斷弱全域引用是否有效時候,返回JNI_FALSE,證明其指向對象有效。

2、這時Java虛擬機器進行了記憶體回收,回收了弱全域引用指向的對象。

3、這樣如果我們後面訪問弱全域引用指向的對象,將會引發程式崩潰,因為弱全域引用指向對象已經被Java虛擬機器回收了。

    根據JNI標準手冊《Weak Global References》中的介紹,我們可以有這樣一個使用弱全域引用的方案。在使用全域引用之前,我們先通過NewLocalRef函
數建立一個局部引用,然後使用這個局部引用來訪問該對象進行處理,當完成處理之後,刪除局部引用。局部引用可以阻止Java虛擬機器回收其指向的對象,這樣
可以保證在處理期間弱全域引用和局部引用指向的對象不會被Java虛擬機器回收。假如弱全域引用指向對象已經被Java虛擬機器回收,則NewLocalRef函數將會返回NULL,則建立局部引用失敗,這個傳回值有助於我們判斷是否需要重新初始化弱全域引用。我們可以寫出如下的代碼:

static jobject weak_global_ref = NULL;jobject local_ref;/* We ensure create local_ref success */、while ( week_global_ref == NULL    || (local_ref = NewLocalRef(env, weak_global_ref)) == NULL ){    /* Init week global referrence again */    weak_global_ref = NewWeakGlobalRef(...);}/* Process local_ref */.....(*env)->DeleteLocalRef(env, local_ref);

    注意在《Java Native Interface: Programmer’s Guide and Specification》的例子中,有很多不是按照如上的代碼實現的,那些代碼是有潛在風險的,請各位朋友注意。

    弱全域引用的有效期間和全域引用一樣,建立之後除非調用DeleteWeakGlobalRef顯示的刪除,否則將一直有效。並且弱全域引用可以在多個線程之間共用。

    
你可能會問弱全域引用這麼難用,為什麼還要存在呢?Simon也覺得這個東西不好用,但是”存在即合理“,弱全域引用還是有他的用途的。弱全域引用是可以
用來緩衝jclass對象,那麼你可能會問能否用全域引用來緩衝jclass對象呢?答案是不可以。這裡需要簡單介紹一下Native的共用庫的卸載。當
Class Loader釋放完所有的class後,然後Class
Loader會卸載Native的共用庫。如果我們用全域引用來緩衝jclass對象的話,根據前面對全域引用對Java虛擬機器記憶體回收機制的影響,將會
阻止Java虛擬機器回收該對象。則Class Loader也將不能釋放這個jclass對象,進而造成Class
Loader不能卸載Native的共用庫(永遠無法釋放)。如果用弱全域引用來緩衝將不會有這個問題,Java虛擬機器隨時都可以釋放它指向的對象。

總結

    至此我們把JNI規範中的三種引用都進行了一個簡單的介紹,在此我對以上內容做一個簡單總結:

1、局部引用是Native代碼中最常用的引用。大部分局部引用都是通過JNI API返回來建立,也可以通過調用NewLocalRef來建立。另外強烈建議Native函數傳回值為局部引用。局部引用只在當前調用上下文中有效,所以局部引用不能用Native代碼中的靜態變數和全域變數來儲存。另外時刻要記著Java虛擬機器局部引用的個數是有限的,編程的時候強烈建議調用EnsureLocalCapacity和PushLocalFrame來確保Native代碼能夠獲得足夠的局部引用數量。

2、全域變數必須要通過NewGlobalRef建立,通過DeleteGlobalRef刪除。主要用來緩衝Field ID和Method ID。全域引用可以在多線程之間共用其指向的對象。在C語言中以靜態變數和全域變數來儲存。

3、全域引用和局部引用可以阻止Java虛擬機器回收其指向的對象。

4、弱全域引用必須要通過NewWeakGlobalRef建立,通過DeleteWeakGlobalRef銷毀。可以在多線程之間共用其指向的對象。在C語言中通過靜態變數和全域變數來保持弱全域引用。弱全域引用指向的對象隨時都可能會被Java虛擬機器回收,所以使用的時候需要時刻注意檢查其有效性。弱全域引用經常用來緩衝jclass對象。

5、全域引用和弱全域引用可以在多線程中共用其指向對象,但是在多線程編程中需要注意多線程同步。強烈建議在JNI_OnLoad初始化全域引用和弱全域引用,然後在多線程中進行讀全域引用和弱全域引用,這樣不需要對全域引用和弱全域引用同步(只有讀操作不會出現不一致情況)。

    本文和前文《Android JNI編程提高篇之一》是我對《Java Native Interface: Programmer’s Guide and Specification》學習的一個總結。只包括了我認為最難的引用部分,JNI編程還有很多其他方面需要學習的方面還很多,大家可以根據《Android JNI開發入門之一》介紹更深入的學習。希望我的這些博文對你學習JNI編程有所協助。也歡迎JNI編程高手來拍磚。

 

原文

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.