GC 僅回收「它認為」的垃圾,而非「你認為」的垃圾。寫出無法回收的代碼會直接導致 OOM。理解 GC 行為是記憶體優化前提。
new 出來的物件,先分配在新生代 (Eden)。| 階段 | 說明 | 優化建議 |
|---|---|---|
| 建立 | new 分配記憶體 | 避免循環中 new、避免重複初始化 |
| 應用 | 至少一強引用持有 | 縮小引用作用域 |
| 不可見 | 超出變數作用域 | 用完置 null 加速 GC 發現 |
| 不可達 | 無強引用鏈可達 | — |
| 可收集 | GC 識別為垃圾 | 少用 finalize |
| 終結 | 執行 finalize() | 改用顯式 destroy() + finalize 雙重保險 |
| 釋放 | 記憶體重用 | — |
// 反例:每次迴圈 new 物件,GC 來不及回收
for (int i=0; i<10000; i++) Object obj = new Object();
// 正例:重用引用
Object obj = null;
for (int i=0; i<10000; i++) obj = new Object();
同理,建構子中避免重複初始化:
private Hashtable table = new Hashtable(); // 欄位初始化
public A() { table = new Hashtable(); } // 建構子再初始化 = 兩個物件,一個洩漏!
protected void finalize() throws Throwable {
try {
this.resource = null; // 標記釋放
} finally {
super.finalize(); // 必須呼叫父類 finalize
}
}
警告: finalize 執行時間不可控、增加 GC 負擔。最佳實踐: 提供 destroy() 顯式釋放,finalize 作為最後防線雙重保險。
建構子遞歸調用:父類 → 子類。避免在建構子中初始化大量物件。介面無建構子,天然輕量。
Object huge = new char[10000000];
SoftReference<Object> ref = new SoftReference<>(huge);
// 記憶體緊張時 GC 可回收軟引用指向的物件
適用場景 (四者兼備):
1. 物件體積大 2. 生命週期長 3. 資料穩定 4. 多實例共享需求。
否則慎用 — 長生命週期難回收,反而增加記憶體壓力。
public abstract class ObjectPool {
private Hashtable locked, unlocked;
private long expirationTime;
protected abstract Object create();
protected abstract void expire(Object o);
protected abstract boolean validate(Object o);
public synchronized Object getObject() { ... }
public synchronized void freeObject(Object o) { ... }
}
透過池化重用昂貴物件 (DB 連線、執行緒、解析器),避免頻繁建構/銷毀。
java -XX:NewSize=128m -XX:MaxNewSize=128m -XX:SurvivorRatio=8 -Xms512m -Xmx512m
obj = null)finalize (增加 GC 工作量)SoftReferenceSystem.gc() 強制 GC (干擾自適應調節)高效能 Java 記憶體管理 = 理解 GC 行為 + 程式碼層面避免洩漏/加速回收 + JVM 參數適度調優。核心心法:物件「用完即棄」(置 null)、大物件「軟引用守門」、昂貴物件「池化重用」、參數「固定堆避免震盪」。