04、Java四種引用:強引用,軟引用,弱引用,虛引用

目錄

Java中根據其生命週期的長短,將引用分爲4類:強引用、 軟引用、弱引用、虛引用

強引用(舉例):

軟引用(舉例):

弱引用(舉例):

虛引用(舉例):

1 強引用(Strong" Reference)

2 軟引用(SoftReference)

3 弱引用(WeakReference)

4 虛引用

我的理解


在Java語言中,除了基本數據類型外,其他的都是指向各類對象的對象引用;

Java中根據其生命週期的長短,將引用分爲4類:強引用、 軟引用、弱引用、虛引用

強引用(舉例):

只要引用存在,垃圾回收器永遠不會回收
Object obj = new Object();
//可直接通過obj取得對應的對象 如obj.equels(new Object());
而這樣 obj對象對後面new Object的一個強引用,只有當obj這個引用被釋放之後,對象纔會被釋放掉,這也是我們經常所用到的編碼形式。

 

軟引用(舉例):

非必須引用,內存溢出之前進行回收,可以通過以下代碼實現
Object obj = new Object();
SoftReference<Object> sf = new SoftReference<Object>(obj);
obj = null;
sf.get();//有時候會返回null
這時候sf是對obj的一個軟引用,通過sf.get()方法可以取到這個對象,當然,當這個對象被標記爲需要回收的對象時,則返回null;
軟引用主要用戶實現類似緩存的功能,在內存足夠的情況下直接通過軟引用取值,無需從繁忙的真實來源查詢數據,提升速度;當內存不足時,自動刪除這部分緩存數據,從真正的來源查詢這些數據。

 

弱引用(舉例):

第二次垃圾回收時回收,可以通過如下代碼實現
Object obj = new Object();
WeakReference<Object> wf = new WeakReference<Object>(obj);
obj = null;
wf.get();//有時候會返回null
wf.isEnQueued();//返回是否被垃圾回收器標記爲即將回收的垃圾
弱引用是在第二次垃圾回收時回收,短時間內通過弱引用取對應的數據,可以取到,當執行過第二次垃圾回收時,將返回null。
弱引用主要用於監控對象是否已經被垃圾回收器標記爲即將回收的垃圾,可以通過弱引用的isEnQueued方法返回對象是否被垃圾回收器標記。

 

虛引用(舉例):

垃圾回收時回收,無法通過引用取到對象值,可以通過如下代碼實現
Object obj = new Object();
PhantomReference<Object> pf = new PhantomReference<Object>(obj);
obj=null;
pf.get();//永遠返回null
pf.isEnQueued();//返回是否從內存中已經刪除
虛引用是每次垃圾回收的時候都會被回收,通過虛引用的get方法永遠獲取到的數據爲null,因此也被成爲幽靈引用。
虛引用主要用於檢測對象是否已經從內存中刪除。

我來解釋一下上圖的具體狀態,這是 Java 定義的不同可達性級別(reachability level),具體如下:

  • 強可達(Strongly Reachable),就是當一個對象可以有一個或多個線程可以不通過各種引用訪問到的情況。比如,我們新創建一個對象,那麼創建它的線程對它就是強可達。
  • 軟可達(Softly Reachable),就是當我們只能通過軟引用才能訪問到對象的狀態。
  • 弱可達(Weakly Reachable),類似前面提到的,就是無法通過強引用或者軟引用訪問,只能通過弱引用訪問時的狀態。這是十分臨近 finalize 狀態的時機,當弱引用被清除的時候,就符合 finalize 的條件了。
  • 幻象可達(Phantom Reachable),就是沒有強、軟、弱引用關聯,並且 finalize 過了,只有幻象引用指向這個對象的時候。
  • 當然,還有一個最後的狀態,就是不可達(unreachable),意味着對象可以被清除了。

1 強引用(Strong" Reference)

特點:我們平常典型編碼Object obj = new Object()中的obj就是強引用。通過關鍵字new創建的對象所關聯的引用就是強引用。 當JVM內存空間不足,JVM寧願拋出OutOfMemoryError運行時錯誤(OOM),使程序異常終止,也不會靠隨意回收具有強引用的“存活”對象來解決內存不足的問題。對於一個普通的對象,如果沒有其他的引用關係,只要超過了引用的作用域或者顯式地將相應(強)引用賦值爲 null,就是可以被垃圾收集的了,具體回收時機還是要看垃圾收集策略。

應用場景:項目中到處都是。

2 軟引用(SoftReference)

特點:軟引用通過SoftReference類實現。 軟引用的生命週期比強引用短一些。只有當 JVM 認爲內存不足時,纔會去試圖回收軟引用指向的對象:即JVM 會確保在拋出 OutOfMemoryError 之前,清理軟引用指向的對象。我們可以調用ReferenceQueue的poll()方法來檢查是否有它所關心的對象被回收。如果隊列爲空,將返回一個null,否則該方法返回隊列中前面的一個Reference對象。軟引用可以和一個引用隊列(ReferenceQueue)聯合使用,如果軟引用所引用的對象被垃圾回收器回收,Java虛擬機就會把這個軟引用加入到與之關聯的引用隊列中。

應用場景:圖片緩存框架中,“內存緩存”中的圖片是以這種引用來保存,使得JVM在發生OOM之前,可以回收這部分緩存。


3 弱引用(WeakReference)

弱引用通過WeakReference類實現。 弱引用的生命週期比軟引用短。在垃圾回收器線程掃描它所管轄的內存區域的過程中,一旦發現了具有弱引用的對象,不管當前內存空間足夠與否,都會回收它的內存。由於垃圾回收器是一個優先級很低的線程,因此不一定會很快回收弱引用的對象。弱引用可以和一個引用隊列(ReferenceQueue)聯合使用,如果弱引用所引用的對象被垃圾回收,Java虛擬機就會把這個弱引用加入到與之關聯的引用隊列中。

應用場景:在靜態內部類中,經常會使用弱引用。例如,一個類發送網絡請求,承擔callback的靜態內部類,則常以虛引用的方式來保存外部類(宿主類)的引用,當外部類需要被JVM回收時,不會因爲網絡請求沒有及時回來,導致外部類不能被回收,引起內存泄漏。


4 虛引用

特點:虛引用也叫幻象引用,通過PhantomReference類來實現。無法通過虛引用訪問對象的任何屬性或函數。幻象引用僅僅是提供了一種確保對象被 finalize 以後,做某些事情的機制。如果一個對象僅持有虛引用,那麼它就和沒有任何引用一樣,在任何時候都可能被垃圾回收器回收。虛引用必須和引用隊列 (ReferenceQueue)聯合使用。當垃圾回收器準備回收一個對象時,如果發現它還有虛引用,就會在回收對象的內存之前,把這個虛引用加入到與之關聯的引用隊列中。

ReferenceQueue queue = new ReferenceQueue ();
PhantomReference pr = new PhantomReference (object, queue); 

程序可以通過判斷引用隊列中是否已經加入了虛引用,來了解被引用的對象是否將要被垃圾回收。如果程序發現某個虛引用已經被加入到引用隊列,那麼就可以在所引用的對象的內存被回收之前採取一些程序行動。

應用場景:這種引用的get()方法返回總是null,所以,可以想象,在平常的項目開發肯定用的少。但是根據這種引用的特點,我想可以通過監控這類引用,來進行一些垃圾清理的動作。

 

我的理解

 

  • 強引用就像大老婆,關係很穩固。
  • 軟引用就像二老婆,隨時有失寵的可能,但也有扶正的可能。
  • 弱引用就像情人,關係不穩定,可能跟別人跑了。
  • 幻像引用就是夢中情人,只在夢裏出現過。

 

 

 

發佈了96 篇原創文章 · 獲贊 19 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章