對象在 JVM 中從誕生到消亡,經歷怎樣的旅程?理解生命周期對內存優化、避免洩漏、排查 OOM 至關重要。本文劃分七大階段,詳細剖析四種引用類型語義與應用場景。
finalize() 執行(若覆寫且未被調用過)<init> 方法(字段初始化、構造器代碼)// 錯誤
for (int i=0; i<10000; i++) { Object obj = new Object(); ... }
// 正確
Object obj = null;
for (int i=0; i<10000; i++) { obj = new Object(); ... }
null,縮短強引用壽命// 違規:Hashtable 初始化兩次
class A { Hashtable table = new Hashtable();
A() { table = new Hashtable(); } }
// 正確
class B { Hashtable table = new Hashtable();
B() { } }

微小差別導致性能數量級差距,「勿以惡小而為之」。

| 引用類型 | GC 行為 | 典型場景 | 代碼模式 |
|---|---|---|---|
| 強引用 | 永不回收(OOM 也不行) | 常規對象持有 | Object obj = new Object(); |
| 軟引用 | 內存不足時回收 | 緩存、對象池 | SoftReference |
| 弱引用 | GC 必回收 | WeakHashMap、監聽器 | WeakReference |
| 虛引用 | 最終化後、回收前 | 直接內存釋放、清理追蹤 | PhantomReference |
SoftReference cache = new SoftReference<>(loadBigData());
// 使用時
BigData data = cache.get();
if (data == null) { // 被 GC 回收
data = loadBigData();
cache = new SoftReference<>(data);
}
// 保證:拋出 OOM 前必清理軟引用
優勢:最大化內存利用、防 OOM。劣勢:重建開銷大、狀態丟失需權衡。
WeakReference ref = new WeakReference<>(obj);
// 或指定隊列
ReferenceQueue queue = new ReferenceQueue<>();
WeakReference ref = new WeakReference<>(obj, queue);
WeakHashMap:Key 為弱引用,Key 無強引用時自動移除條目finalize() 後、內存回收前被虛引用持有ReferenceQueue 實現「比 finalize 更靈活的清理」DirectByteBuffer)、原生資源清理開發者可主動加速:obj = null; 縮短強引用鏈,幫助 GC 更早發現垃圾。
finalize() 只被調用一次,異常被忽略try-with-resources、Cleaner (Java 9+)、PhantomReferencenull)、集合清理SoftReference、配合 ReferenceQueue 監控WeakHashMap、弱引用監聽器模式try-with-resources 替代 finalize