首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java finalize() 終結方法詳解:運作機制、風險與最佳替代方案

     編輯:Java 相關知識

什麼是 finalize()?

protected void finalize() throws Throwable 是 Object 類別定義的方法,意圖在物件被垃圾回收前執行清理工作(如關閉檔案、釋放原生資源)。它與建構子相反:建構子初始化,終結子清理。

運作流程與陷阱

  1. 物件變為不可達時,不會立即回收,而是被放入「終結佇列」。
  2. 專屬的低優先級「Finalizer」執行緒逐一執行 finalize()。
  3. finalize() 成功完成後,物件才在下一輪 GC中真正被回收(至少兩次 GC 週期)。
  4. JVM 不保證 finalize() 會被呼叫(程式結束、GC 不執行等情況)。
  5. 若 finalize() 拋出未捕獲例外,終結流程中止,物件可能永不被回收。
  6. 大量含 finalize() 物件會導致 Finalizer 執行緒跟不上,佇列堆積,最終觸發 OutOfMemoryError。

程式碼示範:finalize() 中呼叫 Thread.yield() 導致記憶體耗盡

public class ObjectWYieldFinalizer {
    @Override
    protected void finalize() throws Throwable {
        Thread.yield(); // 讓出 CPU,Finalizer 執行緒反覆暫停
    }
}

public class TestObjectWYieldFinalizer {
    public static void main(String[] args) {
        while (true) {
            new ObjectWYieldFinalizer(); // 持續產生物件,Finalizer 來不及處理
        }
    }
}

執行結果:記憶體快速耗盡,拋出 java.lang.OutOfMemoryError。

最佳替代方案

  • try-with-resources (JDK 7+):自動關閉實作 AutoCloseable 的資源,編譯期保證釋放。
  • java.lang.ref.Cleaner (JDK 9+):比 finalize() 更輕量、可控的清理機制。
  • 顯式 close()/dispose() 方法:由呼叫端負責在 finally 區塊釋放。

結論

finalize() 具備不可預測的執行時機、效能負擔、記憶體洩漏風險,不應依賴它進行關鍵資源釋放。現代 Java 開發應改用上述確定性釋放模式。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved