JDK 1.2 引入四種引用類型,配合 GC 實現靈活內存管理。按強度遞減:
強引用 > 軟引用 > 弱引用 > 虛引用
Object obj = new Object(); // 最普遍
String str = "hello";
OutOfMemoryError 也不回收obj = null 或離開作用域public void clear() {
modCount++;
for (int i = 0; i < size; i++)
elementData[i] = null; // 逐個置 null,釋放強引用
size = 0;
}
優於 elementData = null:保留數組容量,避免擴容開銷。
SoftReference sr = new SoftReference<>("abc");
BrowserPage page = loadPage(url);
SoftReference cache = new SoftReference<>(page);
// 用戶點後退
if (cache.get() != null) {
show(cache.get()); // 緩存命中,極快
} else {
page = loadPage(url); // 緩存被回收,重新加載
cache = new SoftReference<>(page);
}
ReferenceQueue q = new ReferenceQueue<>();
SoftReference sr = new SoftReference<>("abc", q);
// 被回收後,sr 自動入隊 q
String ref = q.poll(); // 可輪詢處理回收後邏輯
WeakReference wr = new WeakReference<>("abc");
// Key 為弱引用,Key 無強引用時自動移除條目
Map cache = new WeakHashMap<>();
cache.put(new CacheKey("user:1"), data);
// CacheKey 無其他引用 → 下次 GC 後條目自動消失
PhantomReference
get() 永遠返回 null// 內部持有 PhantomReference
// GC 回收 DirectByteBuffer 時,PhantomReference 入隊
// 專用線程輪詢隊列,調用 unsafe.freeMemory(address)
| 引用類型 | GC 回收時機 | get() 返回 | 需隊列 | 典型場景 |
|---|---|---|---|---|
| 強引用 | 從不(除非 OOM) | 對象 | 否 | 正常業務對象 |
| 軟引用 | 內存不足時 | 對象/null | 可選 | 高速緩存 |
| 弱引用 | 下次 GC 時 | 對象/null | 可選 | 非必須映射、監聽器 |
| 虛引用 | 下次 GC 時 | 永遠 null | 必須 | 回收追蹤、堆外內存釋放 |
GC Roots → 強引用鏈 → 對象(強可達,不回收)
GC Roots → 軟引用鏈 → 對象(軟可達,內存不足回收)
GC Roots → 弱引用鏈 → 對象(弱可達,必回收)
GC Roots → 虛引用鏈 → 對象(虛可達,必回收,入隊通知)
WeakReference)掌握四大引用,能讓你從「被動接受 GC」轉向「主動設計內存策略」,是高性能 Java 應用、中間件開發的必備內功。