| 引用類型 | 強度 | 回收時機 | 典型用途 |
| Strong Reference | 最強 | 永不主動回收 | 一般物件持有 |
| Soft Reference | 次強 | 記憶體不足 (OOM) 前 | 快取、圖片緩存 |
| Weak Reference | 弱 | 下次 GC 時 | 快取、監聽器、WeakHashMap Key |
| Phantom Reference | 最弱 | 最終化後、回收前 | 直接記憶體釋放追蹤 |
WeakReference 使用示例
public class TestWeakReference {
public static void main(String[] args) throws Exception {
UserInfo user = new UserInfo("Jim Green");
UserInfo strongRef = user; // 強引用
WeakReference<UserInfo> weakRef = new WeakReference<>(user);
System.out.println("GC 前 - 強引用: " + strongRef);
System.out.println("GC 前 - 弱引用: " + weakRef.get());
user = null; // 斷開原強引用
System.gc(); // 請求 GC
System.out.println("GC 後 - 強引用: " + strongRef); // 仍存在
System.out.println("GC 後 - 弱引用: " + weakRef.get()); // 仍存在(因 strongRef 仍指向)
strongRef = new UserInfo("Jim White"); // 覆蓋強引用
System.gc();
System.out.println("再次 GC - 強引用: " + strongRef);
System.out.println("再次 GC - 弱引用: " + weakRef.get()); // null,已被回收
}
}
class UserInfo {
private String name;
public UserInfo(String name) { this.name = name; }
@Override public String toString() { return "Name: " + name; }
}
輸出結果
GC 前 - 強引用: Name: Jim Green
GC 前 - 弱引用: Name: Jim Green
GC 後 - 強引用: Name: Jim Green
GC 後 - 弱引用: Name: Jim Green
再次 GC - 強引用: Name: Jim White
再次 GC - 弱引用: null
內部實現原理
UML 關係
Reference (抽象基類) → WeakReference (簡單繼承)
ReferenceQueue:GC 將回收的引用入隊,供應用輪詢。
Reference 核心字段
private T referent; // 所引用的物件
private ReferenceQueue<? super T> queue; // 可選隊列
private Reference next; // 隊列節點指針
// 狀態隱式由 next 指向判斷:null=Active, this=Inactive/Enqueued 末尾, 其他=隊列中
四種狀態流轉
- Active:剛建立,
next=null。
- Pending:GC 發現 referent 可回收且有 queue,放入
pending 靜態鏈表。
- Enqueued:
ReferenceHandler 守護線程處理 pending,入 queue,next 指向隊列下一個。
- Inactive:從 queue 移除或無 queue 直接轉入,
next=this。
ReferenceHandler 守護線程
private static class ReferenceHandler extends Thread {
public void run() {
for (;;) {
Reference r;
synchronized (lock) {
if (pending != null) {
r = pending;
pending = (r.next == r) ? null : r.next;
r.next = r; // 標記為 Enqueued
} else {
lock.wait(); // 等待 GC 喚醒
}
}
if (r instanceof Cleaner) ((Cleaner)r).clean();
else if (r.queue != ReferenceQueue.NULL) r.queue.enqueue(r);
}
}
}
關鍵點:GC 負責 Active→Pending,ReferenceHandler 負責 Pending→Enqueued。
ReferenceQueue 入隊/出隊
boolean enqueue(Reference<? extends T> r) {
synchronized (r) {
if (r.queue == ENQUEUED) return false;
synchronized (lock) {
r.queue = ENQUEUED;
r.next = (head == null) ? r : head; // 頭插法
head = r;
queueLength++;
lock.notifyAll();
return true;
}
}
}
WeakHashMap 原理預覽
- Key 使用
WeakReference,Value 為強引用。
- 當 Key 無強引用時,GC 回收 Key,對應 Entry 在下次操作 (get/put/resize) 時被清理。
- 適合「Key 生命週期由外部控制」的快取場景。
總結
WeakReference 讓物件在「無強引用時」可被 GC 回收。
- 配合
ReferenceQueue 可感知回收事件,做清理工作。
- 實現依賴 GC 與
ReferenceHandler 協作,狀態由 next 指針隱式標記。
- 濫用會導致頻繁 GC、效能抖動,請謹慎使用。
- 上一篇文章: Java 環境變數配置原理深度解析:Path、Classpath 與 JDK 目錄結構
- 下一篇文章: Eclipse 在線安裝 Hibernate Tools 插件完整教程
Copyright ©
程式碼之家 All Rights Reserved