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

Java 垃圾回收機制淺析:從基礎概念到引用類型

     編輯:Java 相關知識

重讀 James Gosling 的《Java 程式設計語言》後,整理了一些關於 Java 垃圾回收(Garbage Collection,GC)的筆記,這裡與大家分享核心觀念。

一、垃圾回收基本原理

在 Java 中,物件透過 new 關鍵字建立於堆疊,但沒有對應的 delete 操作來手動釋放記憶體。當我們不再需要某個物件時,只需消除對它的引用,具體方式有三種:

  • 將引用指向其他物件
  • 將引用設為 null
  • 離開方法作用域,導致區域變數消失

核心規則: 當程式碼無法再以任何路徑觸達某個物件時,該物件佔用的空間即符合回收資格。

GC 的最大優勢在於消除「懸空引用」問題。在允許手動管理記憶體的語言中,若物件被釋放後仍有引用指向它,便會產生 dangling reference。Java 的自動回收機制從根本上避免了這類錯誤。

常見 GC 演算法模型

  • 引用計數法: 簡單但無法處理循環引用。
  • 標記-清除: 先標記所有可觸達物件,再清除未標記者。這是現代 JVM 的基礎模型。

二、finalize 方法與覆寫注意事項

finalize() 會在 GC 確定物件不可觸達、準備回收記憶體前被呼叫。重點如下:

  • 用於釋放非記憶體資源(如檔案控制代碼、網路連線)。
  • 每個物件最多只會被呼叫一次;即使在 finalize 中讓物件「復活」,後續再變不可觸達也不會再次觸發。
  • 呼叫時機不確定,甚至可能永遠不被呼叫(如 JVM 關閉時)。

覆寫 finalize 的最佳實踐

@Override
protected void finalize() throws Throwable {
    try {
        // 釋放自身持有的非記憶體資源
    } finally {
        super.finalize(); // 確保父類清理邏輯執行
    }
}

注意:super.finalize() 建議放在 finally 區塊,保證執行。此外,物件被標記為垃圾時,它引用的其他物件可能已先被回收,狀態不可預期,因此 finalize 中不應依賴其他物件的狀態。

三、與 GC 互動的核心類別與方法

主要透過 Runtime.getRuntime() 或 System 類別:

  • gc():建議執行垃圾回收
  • runFinalization():建議執行待處理的 finalize 方法
  • freeMemory()、totalMemory()、maxMemory():記憶體資訊查詢

System.gc() 與 System.runFinalization() 內部會委派給 Runtime 實例對應方法。

四、可觸達性狀態與引用類型

物件只有在「無任何引用指向」時才會被視為垃圾。但有時希望在仍有引用存在的情況下讓物件可被回收,這時需用到 java.lang.ref 套件下的引用物件。

引用強度與可觸達性層級

層級類別特性
強可觸達普通引用預設狀態,絕不會被回收
軟可觸達SoftReference記憶體不足時才會回收;拋出 OutOfMemoryError 前保證已清除
弱可觸達WeakReference下一次 GC 即會回收,適合快取場景
虛可觸達PhantomReferenceget() 永遠回傳 null;需配合 ReferenceQueue 追蹤物件終結,確保 finalize 已執行後再做清理
不可觸達無引用鏈可被直接回收

Reference 類別常用方法

  • get():取得被引用物件(虛引用除外)
  • clear():手動清除引用
  • enqueue() / isEnqueued():佇列操作

理解這四種引用強度,能讓我們在快取、資源管理等場景更精準地控制物件生命週期,充分發揮 GC 的彈性。

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