首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java GC 與四大引用類型深度解析:強、軟、弱、虛擬引用

     編輯:Java 相關知識

Java 提供四種引用類型,與垃圾回收(GC)機制緊密配合,靈活控制物件生命週期。理解它們差異對記憶體優化、快取設計至關重要。

四大引用類型對比

引用類型用途GC 回收時機典型應用
Strong Reference
(強引用)
預設引用方式無強引用指向時才回收一般物件持有
Soft Reference
(軟引用)
記憶體不足前保留OOM 前回收記憶體敏感快取
Weak Reference
(弱引用)
僅在使用中保留GC 發現僅弱引用時回收WeakHashMap、監聽器
Phantom Reference
(虛擬/幽靈引用)
追蹤回收時機finalize 後、記憶體釋放前資源清理、分散式 GC

代碼示例與行為驗證

1. 強引用

Object referent = new Object();
Object strongRef = referent;
referent = null;
System.gc();
assertNotNull(strongRef); // GC 後仍存在

2. 軟引用

SoftReference<Object> softRef = new SoftReference<>(referent);
referent = null;
System.gc();
assertNotNull(softRef.get()); // 記憶體充足時保留

3. 弱引用與 WeakHashMap

WeakReference<Object> weakRef = new WeakReference<>(referent);
referent = null;
System.gc();
assertNull(weakRef.get()); // GC 後立即回收

// WeakHashMap: key 為弱引用,無強引用時自動移除 entry
Map<Object, Object> map = new WeakHashMap<>();
Object key = new Object();
map.put(key, "value");
key = null;
System.gc();
Thread.sleep(1000); // 等待 ReferenceQueue 處理
assertFalse(map.containsValue("value"));

4. 虛擬引用與 ReferenceQueue

ReferenceQueue<Object> queue = new ReferenceQueue<>();
PhantomReference<Object> phantomRef = new PhantomReference<>(referent, queue);
// phantomRef.get() 永遠回傳 null

referent = null;
System.gc();
assertTrue(phantomRef.isEnqueued());
Reference<?> removed = queue.remove(); // 取得被回收的引用
assertNotNull(removed);

虛擬引用的獨特價值

  1. 精確掌握回收時機:在 finalize() 執行後、記憶體真正釋放前入隊,適合資源清理(如 DirectBuffer 釋放、分散式 GC)
  2. 避免 finalize 復活問題:物件在 finalize() 中重建強引用會導致 GC 失敗甚至 OOM,虛擬引用在 finalize 後處理,規避此風險

ReferenceQueue 統一機制

軟、弱、虛擬引用皆可指定 ReferenceQueue,GC 回收物件前將引用入隊,應用程式可輪詢隊列執行清理邏輯(WeakHashMap 即利用此機制清理無效 entry)。

實務建議

  • 快取優先用 SoftReference 或 Guava Cache / Caffeine 等成熟框架
  • 監聽器、回調持有用 WeakReference 避免記憶體洩漏
  • 底層資源管理、框架開發考慮 PhantomReference
  • 一般業務代碼極少直接使用引用 API,但理解原理有助於 GC 調優與疑難雜症排查
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved