天天看點

強引用、軟引用、弱引用、虛引用有什麼差別?強引用“一直存活着”軟引用“有 n 次活的機會”弱引用“回收就會死亡”虛引用“随時可能被回收”參考資料

強引用、軟引用、弱引用、虛引用 · 語雀 (yuque.com)

自 JDK1.2 開始,Java 提供了 4 種引用關系,以表示引用和執行個體對象的關系。

強引用“一直存活着”

強引用,就是我們最常見的普通對象引用。

隻要強引用還存在,垃圾收集器永遠不會回收掉被引用的執行個體對象。

Object o = new Object();
           

軟引用“有 n 次活的機會”

在系統将要發生記憶體溢出異常之前,垃圾收集器會把隻被軟引用關聯着的執行個體對象進行回收,如果這次回收還沒有足夠的記憶體,才會抛出記憶體溢出異常(OutOfMemoryError)。

軟引用通常用來實作記憶體敏感的緩存:

  • 如果還有空閑記憶體,就可以暫時保留緩存;
  • 如果記憶體不足,則清理掉緩存;

這樣就保證了使用緩存的同時,不會耗盡記憶體。

SoftReference<Object> softO = new SoftReference<>(new Object());
           

弱引用“回收就會死亡”

被弱引用關聯着的執行個體對象隻能生存到下一次垃圾收集發生之前,當垃圾收集器工作時,無論目前記憶體是否足夠,都會回收掉隻被弱引用關聯的執行個體對象。

弱引用可以用來建構一種沒有特定限制的關系,比如,維護一種非強制性的映射關系,如果試圖擷取時對象還在,就使用它,否則重制執行個體化。弱引用同樣是很多緩存實作的選擇。

WeakReference<Object> weakO = new WeakReference(new Object());
           

虛引用“随時可能被回收”

虛引用也稱為“幽靈引用”或者“幻影引用”,虛引用是最弱的一種引用關系。

  • 在Java 8以及之前的版本中,在虛引用回收後,虛引用指向的對象才會回收。
  • 在Java 9以及更新的版本中,虛引用不會對對象的生存時間産生任何影響。

無法通過虛引用來擷取一個執行個體對象。

虛引用主要用來跟蹤對象被垃圾回收的活動,回收對象關聯的資源。

Object counter = new Object();
ReferenceQueue refQueue = new ReferenceQueue<>();
PhantomReference<Object> p = new PhantomReference<>(counter, refQueue);
counter = null;
System.gc();
try {
    // Remove 是一個阻塞方法,可以指定 timeout,或者選擇一直阻塞
    Reference<Object> ref = refQueue.remove(1000L);
    if (ref != null) {
        // do something
        
        ref = null;
    }
} catch (InterruptedException e) {
    // Handle it
}
           

參考資料