Thinking in Java 示範程式:在迴圈中大量建立 Chair 物件(不保留引用),觀察 finalize() 執行時機與數量。執行結果顯示:建立數萬個物件後,finalize() 才開始陸續執行,且執行數量遠少於建立數量;若手動呼叫 System.gc()、System.runFinalization() 或設定 runFinalizersOnExit(true),才會看到全部物件被終結。
finalize() 可能延遲秒級、分鐘級,甚至程式結束前永不執行。finalize() 執行間有任意間隙。範例中 created 計數器持續遞增,而 finalized 落後數萬。finalize() 至多執行一次。若 finalize() 中重新建立強引用(復活),下次 GC 不會再呼叫 finalize()。finalize() 拋出未捕獲例外會被 JVM 忽略,導致後續終結動作中斷,極難除錯。finalize() 的物件需額外進入 Finalizer 佇列、由專用執行緒處理,延長 GC 週期、增加記憶體壓力。finalize() 兩者皆無保證。AutoCloseable 介面,編譯器自動生成 finally 區塊呼叫 close(),確保及時釋放。
try (FileInputStream fis = new FileInputStream("a.txt");
BufferedReader br = new BufferedReader(new InputStreamReader(fis))) {
// 使用資源
} // 自動關閉,即使發生例外
close(),呼叫端負責在 finally 區塊調用。finalize() 更可控的清理機制,但仍非即時,適用於原生記憶體釋放等非關鍵資源。finalize() 是「最後防線」,僅供記錄、統計等非關鍵清理。**切勿依賴它管理稀缺資源**。採用 try-with-resources 或顯式 close() 才是專業、可靠的資源管理之道。