1. Object aobj = new Object();
2. Object bobj = new Object();
3. Object cobj = new Object();
4. aobj = bobj;
5. aobj = cobj;
6. cobj = null;
7. aobj = null;
問題:第幾行建立的物件符合 GC 回收條件?
| 行號 | 操作 | 堆中物件狀態 | 可達性分析 |
|---|---|---|---|
| 1 | `aobj` → ObjA | ObjA: 被 aobj 參考 | 可達 |
| 2 | `bobj` → ObjB | ObjB: 被 bobj 參考 | 可達 |
| 3 | `cobj` → ObjC | ObjC: 被 cobj 參考 | 可達 |
| 4 | `aobj = bobj` | **ObjA 失去最後參考** → **不可達** ObjB: 被 aobj、bobj 雙重參考 | **ObjA 符合回收** |
| 5 | `aobj = cobj` | ObjB: 僅被 bobj 參考 ObjC: 被 aobj、cobj 雙重參考 | ObjA 已不可達 |
| 6 | `cobj = null` | ObjC: 僅被 aobj 參考 | ObjC 仍可達 (經 aobj) |
| 7 | `aobj = null` | **ObjC 失去最後參考** → **不可達** ObjB: 仍被 bobj 參考 | **ObjC 符合回收** |
**「一個物件是否存活,取決於它是否可從 GC Roots 經由引用鏈到達。」**
GC Roots 包含:
若物件到 GC Roots 沒有任何引用鏈相連,**即為不可達**,標記為可回收 (經過兩次標記:第一次標記不可達,第二次在 Finalizer 佇列確認無復活才真正回收)。
| 引用類型 | 回收行為 | 用途 |
|---|---|---|
| 強引用 | 永不回收 (寧願 OOM) | 普遍物件 `Object obj = new Object()` |
| 軟引用 | 記憶體不足前回收 | 快取 |
| 弱引用 | 下次 GC 必回收 | 快取、監聽器 |
| 虛引用 | 不影響生命週期,回收前收到通知 | 直接記憶體管理 |
範例中 **ObjA (第 1 行建立) 在第 4 行失去引用** 最早可被回收;**ObjC (第 3 行建立) 在第 7 行失去引用** 可被回收。GC 依據**可達性分析**而非單純「不引用就回收」(需經過標記-清除/整理/複製等演算法),且受引用類型影響。理解引用鏈與 GC Roots 是診斷記憶體洩漏的基礎。