系列首篇,建立 Java 記憶體管理心智模型:可達性分析、GC Roots、洩漏本質(游離物件)、一般代碼避免原則,並引出複雜資料結構下需引入 Reference 機制的必要性。
定義:物件已無業務用途,但仍被 GC Roots 直接/間接引用,導致無法回收。
Vector v = new Vector(10);
for (int i = 0; i < 100; i++) {
Object o = new Object();
v.add(o);
o = null; // 僅切斷局部引用,v 仍持有強引用!
}
// 循環結束後,100 個 Object 仍在堆中,無法被 GC 回收 → 記憶體洩漏
圖解:
GC Roots → v (Vector) → [Object, Object, Object...] (100個)
↑
仍可達,不回收
null(特別是長生命週期容器、數組、監聽器、回調)。
public class FileSearch {
private byte[] content; // 錯誤:應為局部變數
public boolean hasString(String str) {
content = new byte[fileSize]; // 佔用大量堆記憶體
loadFile(file, content);
return new String(content).contains(str);
}
}
// 呼叫結束後,content 仍佔用記憶體,除非 FileSearch 實例銷毀
修正:byte[] content = new byte[fileSize]; 作為局部變數,方法結束自動可回收。
緩存、池化、觀察者模式、監聽器列表等場景:
這正是 Reference 機制(軟/弱/虛引用 + ReferenceQueue)登場的舞台。
| 引用類型 | 核心特性 | 適用場景 |
|---|---|---|
| SoftReference | 記憶體不足前回收 | 高命中率緩存(圖片、模板、查詢結果) |
| WeakReference | 下次 GC 回收 | Key 值生命週期綁定、WeakHashMap、監聽器列表 |
| PhantomReference | 回收前瞬間通知 | 直接記憶體釋放、Native 資源清理、對象復活檢測 |