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

Java 垃圾回收機制深度解析:判定演算法、收集策略與主流收集器

     編輯:Java 綜合教學

Java 垃圾回收機制深度解析:判定演算法、收集策略與主流收集器

一、如何判定物件為「垃圾」?

1. 引用計數法

物件維護計數器,引用+1、釋放-1,歸零即回收。缺陷:無法解決循環引用。

MyObject obj1 = new MyObject();
MyObject obj2 = new MyObject();
obj1.ref = obj2;
obj2.ref = obj1;
obj1 = null; obj2 = null;  // 計數器皆為 1,永不回收

Java 不採用此法(Python 採用)。

2. 可達性分析法

從 GC Roots 向下搜尋,無法到達的物件判定為不可達。GC Roots 包含:

  • 虛擬機棧區域引用的物件(區域變數表)
  • 方法區靜態屬性/常量引用的物件
  • 本地方法棧 JNI 引用的物件
  • 同步鎖持有的物件

不可達物件需經歷兩次標記才真正回收:

  1. 第一次標記:發現不可達
  2. 篩選 finalize():必要時執行最終化(不推薦使用)
  3. 第二次標記:確認仍不可達 → 真正回收

3. 參考類型與回收關係

參考類型強度回收時機典型用途
強引用 最強 永不回收(OOM 才回收) 一般物件 Object obj = new Object()
軟引用
SoftReference
次強 記憶體不足前回收 快取、圖片緩存
弱引用
WeakReference
較弱 下次 GC 必回收 快取、監聽器、ThreadLocal
虛引用
PhantomReference
最弱 隨時回收,需配合 ReferenceQueue 直接記憶體管理、堆外記憶體釋放

二、四大經典收集演算法

演算法核心思想優點缺點
標記-清除
(Mark-Sweep)
標記存活,清除其餘 實現簡單 效率低、產生大量記憶體碎片
複製
(Copying)
劃分兩塊,存活者複製換邊 無碎片、分配快(指標碰撞) 50% 空間浪費
標記-整理
(Mark-Compact)
標記後向一端移動存活物件 無碎片、空間利用率高 需移動物件、更新引用,耗時
分代收集
(Generational)
依物件年齡分區,分別用適合演算法 綜合效能最佳,主流 JVM 採用 實現複雜

分代收集具體佈局

  • 新生代:Eden + 2 個 Survivor (S0/S1),採用複製演算法,預設比例 8:1:1
  • 老年代:長期存活物件,採用標記-整理
  • 永久代/元空間:類別元資料、常量、方法描述

GC 過程:Eden+S0 滿 → Minor GC → 存活者複製至 S1 → 清理 Eden+S0 → 角色互換。物件在 Survivor 熬過 MaxTenuringThreshold(預設 15)次 GC 晉升老年代。大物件(大陣列)直接進老年代。

三、HotSpot (JDK 7/8) 主流收集器

收集器類型適用代演算法特點
Serial 單執行緒 新生代 複製 簡單高效,Client 模式預設,STW 暫停
Serial Old 單執行緒 老年代 標記-整理 Serial 老年代版,備用方案
ParNew 多執行緒 新生代 複製 Serial 多執行緒版,搭配 CMS
Parallel Scavenge 多執行緒 新生代 複製 關注吞吐量,自適應調節
Parallel Old 多執行緒 老年代 標記-整理 Parallel Scavenge 老年代版
CMS
(Concurrent Mark Sweep)
並發 老年代 標記-清除 目標最短停頓,碎片問題,JDK 9 棄用
G1
(Garbage First)
並行+並發 全堆(分區) 標記-整理+複製 面向服務端,可預測停頓,JDK 9+ 預設

常用組合

  • Serial + Serial Old:Client 模式預設
  • ParNew + CMS:低延遲需求(JDK 8 常見)
  • Parallel Scavenge + Parallel Old:高吞吐量、批次處理
  • G1:大記憶體、多核、追求平衡(JDK 9+ 預設)

四、記憶體分配與 GC 觸發規則

  1. 優先分配在 Eden
  2. 大物件(需大量連續空間)直接進老年代,-XX:PretenureSizeThreshold 設定閾值
  3. 長期存活物件進老年代,-XX:MaxTenuringThreshold 設定年齡閾值
  4. 動態年齡判定:Survivor 區相同年齡物件總大小 > Survivor 一半,直接晉升
  5. 空間分配擔保:Minor GC 前檢查老年代最大可用連續空間 > 新生代所有物件總大小,否則觸發 Full GC

五、參考資源

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