「弱」引用和「軟」引用(WeakReference、SoftReference)很早以前就被加入了Java API 中,但並不是每個程式設計師都熟悉它們。這表明在理解何處以及如何使用它們方面存在差距。引用類別在垃圾收集的上下文中尤其重要。眾所周知,垃圾收集器本身會釋放物件佔用的內存,但並不是所有程式設計師都知道它是根據物件可用的參考類型來決定釋放記憶體的。 SoftReference和WeakReference之間的主要區別在於收集器如何使用它們。只要弱連結指向某個對象,它就可以隨時刪除該對象,而軟連結的對像只有在JVM確實需要記憶體時才會被收集。由於參考類別的這些特徵,每個參考類別都有自己的用途。SoftReference可用於實現緩存,當JVM需要記憶體時,它將透過刪除此類物件來釋放記憶體。WeakReferences非常適合儲存元數據,例如,儲存類別載入器的連結。如果沒有要載入的類,那麼儲存對ClassLoader 的引用是沒有意義的,只要我們分配它而不是強引用,弱引用就會使 ClassLoader 可以被刪除。在本文中,我們將了解連結類型之間的差異,包括強引用和幻像引用。
Java 中的弱引用與軟引用
對於那些不知道的人,有 4 種類型的連結:- 參考性強
- 弱引用
- 軟參考
- 虛擬參考
Counter counter = new Counter(); // strong reference
WeakReference weakCounter = new WeakReference(counter); //weak reference
counter = null; // now Counter object is eligible for garbage collection
現在,一旦將強引用計數器設為 null (counter = null),第一行中建立的物件就可用於垃圾回收,因為它不再具有強引用。Weak 建立的weakCounter 參考無法阻止收集器刪除Counter 物件。另一方面,如果它是軟引用,則直到JVM對記憶體的需求特別高時,Counter 物件才會被刪除。Java中的軟引用由java.lang.ref.SoftReference類別表示。在Java中建立 SoftReference 的範例
Counter prime = new Counter(); // prime holds a strong reference
SoftReference soft = new SoftReference(prime) ; //soft reference variable has SoftReference to Counter Object
prime = null; // now Counter object is eligible for garbage collection but only be collected when JVM absolutely needs memory
清除強引用(第3行)後,Counter物件將只剩下1個軟引用,這將無法阻止垃圾收集器刪除該對象,但與弱引用不同,它將能夠推遲這個過程直到記憶體嚴重不足。鑑於軟連結和弱連結之間的差異,第一個更適合緩存,而弱連結更適合元資料。一個很好的例子是 WeakHashMap 類,它是 Map 介面(如HashMap或TreeMap類)的後代,但具有一個顯著特徵。WeakHashMap將鍵包裝為弱引用,這意味著只要沒有對物件的強引用,位於WeakHashMap內部的弱引用將無法將您從垃圾收集器中拯救出來。幻象連結是 java.lang.ref 套件中可用的第三種連結。幻像引用由java.lang.ref.PhantomReference類別表示。僅由虛擬連結指向的物件可以隨時被收集器刪除。虛擬連結的建立方式與弱連結或軟連結相同。
DigitalCounter digit = new DigitalCounter(); // digit reference variable has strong reference
PhantomReference phantom = new PhantomReference(digit); // phantom reference
digit = null;
一旦清除了對 DigitalCounter 物件的強烈引用,垃圾收集器將隨時刪除它,因為現在只有幻象引用指向它。除了 WeakReference、SoftReference、PhantomReference、WeakHashMap 類別之外,了解ReferenceQueue類別也很有用。您可以在建立 WeakReference、SoftReference 或 PhantomReference 物件時使用此類:
ReferenceQueue refQueue = new ReferenceQueue(); //reference will be stored in this queue for cleanup
DigitalCounter digit = new DigitalCounter();
PhantomReference phantom = new PhantomReference(digit, refQueue);
物件參考將會被加入到ReferenceQueue中,您可以透過輪詢ReferenceQueue來監視引用的狀態。下圖很好地展示了 Object 的生命週期: 這就是Java中弱引用和軟引用之間的所有差異。我們也熟悉了幻像連結、WeakHashMap類別和ReferenceQueue。正確使用引用將有助於垃圾收集,並使Java中的記憶體管理更加靈活。 來源文章
GO TO FULL VERSION