Java中弱引用、軟引用、虛引用及強引用的區別

本文由 ImportNew -人曉 翻譯自javarevisited。歡迎加入Java小組。轉載請參見文章末尾的要求。

很早Java API就添加了弱引用(WeakReference)和軟引用(SoftReference),但並不是所有的程序員都熟悉這兩個概念。知道弱引用和軟引用的概念與如何使用它們是兩碼事,引用類在垃圾回收工作的過程中有重要作用。我們都知道垃圾回收器會回收符合回收條件的對象的內存,但並不是所有的程序員都知道回收條件取決於指向該對象的引用類型。這正是Java中弱引用和軟引用的主要區別。如果一個對象只有弱引用指向它,垃圾回收器會立即回收該對象,這是一種急切回收方式。相對的,如果有軟引用指向這些對象,則只有在JVM需要內存時纔回收這些對象。弱引用和軟引用的特殊行爲使得它們在某些情況下非常有用。例如:軟引用可以很好的用來實現緩存,當JVM需要內存時,垃圾回收器就會回收這些只有被軟引用指向的對象。而弱引用非常適合存儲元數據,例如:存儲ClassLoader引用。如果沒有類被加載,那麼也沒有指向ClassLoader的引用。一旦上一次的強引用被去除,只有弱引用的ClassLoader就會被回收。這篇文章中我們將講述不同類型的Java引用,例如:強引用(Strong Reference)和虛引用(PhantomReference)。

Java中弱引用VS軟引用

Java中有如下四種類型的引用:

  • 強引用(Strong Reference)
  • 弱引用(WeakReference)
  • 軟引用(SoftReference)
  • 虛引用(PhantomReference)

強引用是我們在編程過程中使用的最簡單的引用,如代碼String s=”abc”中變量s就是字符串對象”abc”的一個強引用。任何被強引用指向的對象都不能被垃圾回收器回收,這些對象都是在程序中需要的。弱引用使用java.lang.ref.WeakReference class 類來表示,你可以使用如下代碼創建弱引用:

Counter counter = new Counter(); // strong reference - line 1
WeakReference<Counter> weakCounter =newWeakReference<Counter>(counter);//weak reference
counter = null;// now Counter object is eligible for garbage collection
現在只要你給強引用對象counter賦空值null,該對象就可以被垃圾回收器回收。因爲該對象此時不再含有其他強引用,即使指向該對象的弱引用weakCounter也無法阻止垃圾回收器對該對象的回收。相反的,如果該對象含有軟引用,Counter對象不會立即被回收,除非JVM需要內存。Java中的軟引用使用java.lang.ref.SoftReference類來表示,你可以使用如下代碼創建軟引用:
Counter prime = new Counter(); // prime holds a strong reference – line 2
SoftReference soft =newSoftReference(prime) ;//soft reference variable has SoftReference to Counter Object created at line 2
 
prime = null;// now Counter object is eligible for garbage collection but only be collected when JVM absolutely needs memory

強引用置空之後,代碼的第二行爲對象Counter創建了一個軟引用,該引用同樣不能阻止垃圾回收器回收對象,但是可以延遲迴收,與弱引用中急切回收對象不同。鑑於軟引用和弱引用的這一區別,軟引用更適用於緩存機制,而弱引用更適用於存貯元數據。另一個使用弱引用的例子是WeakHashMap,它是除HashMap和TreeMap之外,Map接口的另一種實現。WeakHashMap有一個特點:map中的鍵值(keys)都被封裝成弱引用,也就是說一旦強引用被刪除,WeakHashMap內部的弱引用就無法阻止該對象被垃圾回收器回收。

虛引用是java.lang.ref package包中第三種可用的引用,使用java.lang.ref.PhantomReference類來表示。擁有虛引用的對象可以在任何時候被垃圾回收器回收。和弱引用和軟引用相似,你可以通過如下代碼創建虛引用:

DigitalCounter digit =newDigitalCounter();// digit reference variable has strong reference – line 3
PhantomReference phantom =newPhantomReference(digit);// phantom reference to object created at line 3
 
digit = null;

一旦移除強引用,第三行的DigitalCounter對象可以在任何時候被垃圾回收器回收。因爲只有一個虛引用指向該對象,而虛引用無法阻止垃圾回收器回收對象。

除了瞭解弱引用、軟引用、虛引用和WeakHashMap,還需要了解ReferenceQueue。在創建任何弱引用、軟引用和虛引用的過程中你可以通過如下代碼提供引用隊列ReferenceQueue:

ReferenceQueue refQueue =newReferenceQueue();//reference will be stored in this queue for cleanup
DigitalCounter digit =newDigitalCounter();
PhantomReference<DigitalCounter> phantom =newPhantomReference<DigitalCounter>(digit, refQueue);

引用實例被添加在引用隊列中,你可以再任何時候通過查詢引用隊列回收對象。一個對象的生命週期可以通過下圖進行描述:



這就是Java中弱引用和軟引用的區別。我們還學到了一些基本的引用類:弱引用、軟引用、虛引用以及WeakHashMap和WeakHashMap。總之,合理的使用引用可以幫助垃圾回收器更好的管理Java內存。

原文鏈接: javarevisited 翻譯: ImportNew.com- 人曉
譯文鏈接: http://www.importnew.com/10866.html

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