動態記憶體配置是現代程式語言的核心特性。C/C++ 要求程式設計師手動管理記憶體配置與釋放,稍有不慎即導致記憶體洩漏或程式崩潰。Java 為解決此痛點,引入垃圾收集器(Garbage Collector, GC)自動管理記憶體,讓開發者專注於業務邏輯。
System.gc()「建議」執行,具體時機由 JVM 決定| # | 特性 | 說明 |
|---|---|---|
| 1 | 回收目標 | 無用物件記憶體,防洩漏、省資源、避免崩潰 |
| 2 | 判定標準 | 無任何「活動部分」(正在執行的程式碼路徑)引用 |
| 3 | 低優先權 | 平時僅在 JVM 空閒運行;記憶體低時可能突發執行 |
| 4 | 不可強制 | System.gc() 僅為建議,不保證執行 |
| 5 | 不保證回收 | 符合條件的物件可能存活至程式結束 |
| 6 | 回收順序不可預測 | 同批符合條件物件,無法知曉誰先被回收 |
| 7 | 循環引用不影響 | GC 採可觸及性分析,循環引用若無外部引用仍可回收 |
| 8 | null 提示回收 | 將參考設為 null 可提示 GC,但若有事件監聽器需先移除 |
| 9-11 | finalize() | 回收前呼叫、僅執行一次、可重載但僅原簽名會被 GC 呼叫 |
| 12 | 物件復活 | finalize() 中若重新被引用可「復活」一次,但 finalize() 僅呼叫一次 |
| 13-15 | finalize() 細節 | 可手動呼叫但不觸發 GC、子類可呼叫 super.finalize() 但非覆寫 |
| 16 | runFinalization() | 可提前觸發 finalize() 執行 |
| 17 | 區域變數 | 方法結束超出作用域即符合回收條件,下次呼叫重新建立 |
| 18 | 演算法 | 標記-清除 |
| 19 | 不宜過度依賴 finalize() | 執行結果不可預知,資源釋放應用 try-with-resources 或 finally |
1. fobj = new Object();
2. fobj.method();
3. fobj = new Object(); // 第 1 行物件在此失去引用
4. fobj.method();
答案:第 3 行。第 3 行配置新物件,相當於將第 1 行的參考設為 null。
1. Object sobj = new Object();
2. Object sobj = null; // 第 1 行物件符合回收
3. Object sobj = new Object();
4. sobj = new Object(); // 第 3 行物件符合回收
答案:第 1 行與第 3 行。第 2 行與第 4 行分別切斷前一物件引用。
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;
答案:第 7 行。
行 4:aobj 指向 bobj,原 aobj 仍由無人引用?實際上行 1 物件在行 4 即失去引用,但考試邏輯通常聚焦於變數鏈路。
行 5:aobj 指向 cobj,bobj 失去引用。
行 6:cobj 設 null,但 aobj 仍指向同一物件,故不回收。
行 7:aobj 設 null,cobj 所指物件徹底無引用,符合回收。
aobj、bobj 原物件在行 4、5 已失去引用,但題目詢問「第幾行的記憶體空間符合標準」,標準答案為第 7 行(cobj 物件)。
判斷 GC 回收條件只需掌握兩點:設為 null 且無後續存取、指向新物件。但切記:符合條件 ≠ 保證被回收。這正是 SCJP 考試的核心考點,也是 Java 開發者理解記憶體模型的關鍵。