垃圾回收(Garbage Collection, GC)是 Java 自動記憶體管理的核心。深入理解 GC 原理、演算法選擇、調優參數,對於高併發、低延遲系統(如金融交易、即時遊戲、嵌入式裝置)至關重要。本文從 JVM 記憶體模型出發,系統剖析 GC 工作機制、關鍵技術點與實戰優化建議。
JVM 透過「有向圖」管理堆中所有物件:
程式員釋放物件本質是切斷引用鏈(如設為 null),GC 負責後續回收記憶體空間。
採用 Train GC 演算法:
啟動方式:java -Xincgc -jar app.jar。注意:整體吞吐量可能略低於標準 GC。
finalize() 最多執行一次public class ResourceWrapper implements AutoCloseable {
private NativeResource res;
// 主動釋放:try-with-resources 或手動 close()
@Override
public void close() {
if (res != null) {
res.release();
res = null;
}
}
// 被動保底:finalize 只做最後防線
@Override
protected void finalize() throws Throwable {
try {
if (res != null) {
log.warn("資源未正確關閉,由 finalize 強制釋放");
close();
}
} finally {
super.finalize();
}
}
}
java.lang.ref 提供三種引用強度,介於強引用與不可達之間:
| 引用類型 | 回收時機 | 典型應用場景 |
|---|---|---|
| SoftReference | 記憶體不足前 | 圖片快取、記憶體敏感緩存 |
| WeakReference | 下次 GC 必回收 | WeakHashMap、監聽器快取、類別載入器快取 |
| PhantomReference | finalize 後、記憶體釋放前 | 直接記憶體釋放輔助、精確追蹤物件銷毀 |
public class ImageCache {
private final Map> cache = new HashMap<>();
public BufferedImage get(String key) {
SoftReference ref = cache.get(key);
BufferedImage img = (ref != null) ? ref.get() : null;
if (img == null) {
img = loadImage(key); // 重新載入
cache.put(key, new SoftReference<>(img));
}
return img;
}
}
null 加速回收try-with-resources、Cleaner (Java 9+) 管理資源System.gc() 僅建議,非強制;配合 -Xincgc 降低停頓GC 非黑盒,理解其達達性分析、分代假設、演算法權衡,配合引用類型靈活控制物件生命週期,是打造高效能 Java 系統的關鍵。生產環境建議開啟 GC 日誌(-Xlog:gc*:file=gc.log),結合 JVisualVM、Arthas、GCEasy 等工具持續觀測調優。