Java 雖有垃圾回收,但「對象仍被引用卻不再使用」依然會導致內存洩漏。本文深入剖析 GC 根追蹤算法,詳解強/軟/弱/虛四大引用類型,並提供 SoftHashMap 緩存實戰源碼。
Vector v = new Vector(10);
for (int i = 0; i < 100; i++) {
Object o = new Object();
v.add(o);
o = null; // 僅切斷局部引用,v 仍持有對象 → 無法被 GC 回收
}
| 引用類型 | GC 行為 | 典型應用場景 |
|---|---|---|
| 強引用 | 絕不回收,寧願 OOM | 默認對象引用 |
| 軟引用 | 內存不足前回收 | 內存敏感緩存(圖片、數據) |
| 弱引用 | GC 掃描到即回收 | 規範化映射、生命週期長且重建開銷小的對象 |
| 虛引用 | 回收前入隊通知 | 精確追蹤對象銷毀、執行清理操作 |
軟/弱引用對象被回收前,引用本身會入隊 ReferenceQueue;虛引用則在對象內存釋放前入隊,允許最後訪問對象執行清理。
結合 SoftReference + ReferenceQueue + LinkedList 硬引用隊列,實現:
// 核心邏輯片段
private static class SoftValue extends SoftReference {
private final Object key; // 回收時通過 key 從 HashMap 移除
SoftValue(Object k, Object key, ReferenceQueue q) { super(k, q); this.key = key; }
}
public void processQueue() {
SoftValue sv;
while ((sv = (SoftValue) queue.poll()) != null) {
hash.remove(sv.key); // 關鍵:利用外部類訪問內部類私有字段
}
}
obj = null)WeakHashMap、SoftReference 或成熟框架(Caffeine、Guava Cache)OutOfMemoryError