目錄:
- 🧠 一、GC基礎概念
- 1. 什么是垃圾回收(Garbage Collection, GC)?
- 2. 判斷對象是否為垃圾的方法
- 🧩 二、GC核心算法
- 1. 標記-清除算法(Mark-Sweep)
- 2. 標記-整理算法(Mark-Compact)
- 3. 復制算法(Copying)
- 4. 分代收集算法(Generational Collection)
- 📌 三、主流垃圾收集器
- 1. Serial 收集器(串行)
- 2. Parallel Scavenge 收集器(并行)
- 3. CMS(Concurrent Mark Sweep)收集器(并發)
- 4. G1(Garbage-First)收集器(分區)
- 🧱 四、GC收集器對比總結
- 🔄 五、GC類型與觸發條件
- 🧪 六、常見GC異常與調優
- 1. 內存泄漏(Memory Leak)
- 2. 內存溢出(OutOfMemoryError)
- 3. GC調優目標
- 4. GC調優常用參數
- 🧩 七、常見GC問題排查工具
- 📋 八、常見面試題及答案
- 1. CMS 和 G1 的區別?
- 2. G1為何適合大內存?
- 3. CMS的缺點?
- 4. 如何選擇合適的GC收集器?
- 5. Full GC的觸發條件?
- 6. 如何優化GC性能?
- 📚 九、GC調優實踐建議
- ? 十、總結:GC機制核心知識點
- 📄 十一、完整GC日志示例
- 📌 十二、推薦學習資料
🧠 一、GC基礎概念
1. 什么是垃圾回收(Garbage Collection, GC)?
- 作用:自動管理內存,回收不再使用的對象,防止內存泄漏和溢出。
- 核心問題:
(1) 如何判斷對象是垃圾?
(2)如何高效回收垃圾?
2. 判斷對象是否為垃圾的方法
方法 | 說明 |
---|
引用計數法 | 每個對象維護一個引用計數器,引用增加時計數+1,引用失效時-1。無法解決循環引用問題。 |
可達性分析法 | 從GC Roots出發,不可達的對象判定為垃圾。GC Roots包括:虛擬機棧中的局部變量、類靜態屬性引用、常量引用、JNI引用。 |
🧩 二、GC核心算法
1. 標記-清除算法(Mark-Sweep)
- 步驟:
(1)標記:從GC Roots出發,標記所有存活對象。
(2)清除:回收未被標記的對象。 - 缺點:
(1)產生內存碎片(可能導致大對象分配失敗)。
(2)標記和清除效率較低。
2. 標記-整理算法(Mark-Compact)
- 步驟:
(1)標記:同標記-清除。
(2)整理:將存活對象向一端移動,清理邊界外內存。 - 優點:避免內存碎片。
- 缺點:移動對象需要暫停所有線程(Stop-The-World)。
3. 復制算法(Copying)
- 步驟:
(1)將內存分為兩塊,每次只用一塊。
(2)回收時,將存活對象復制到另一塊,清空原區域。 - 優點:高效,無內存碎片。
- 缺點:內存利用率低(只使用一半)。
4. 分代收集算法(Generational Collection)
- 思想:將堆內存劃分為新生代(Young Generation)和老年代(Old Generation)。
- 新生代:對象生命周期短,使用復制算法。
- 老年代:對象生命周期長,使用標記-清除或標記-整理。
📌 三、主流垃圾收集器
1. Serial 收集器(串行)
- 特點:單線程,適用于單核CPU或小內存場景。
- 使用場景:Client模式(如桌面應用)。
- 命令行參數:
-XX:+UseSerialGC
2. Parallel Scavenge 收集器(并行)
- 特點:多線程,關注吞吐量(吞吐優先)。
- 使用場景:后臺計算任務(如批量處理)。
- 命令行參數:
-XX:+UseParallelGC
3. CMS(Concurrent Mark Sweep)收集器(并發)
- 目標:以最短停頓時間為目標,適合高并發、低延遲的Web應用。
- 回收步驟:
(1)初始標記(Initial Mark):暫停所有線程,標記GC Roots直接關聯的對象。
(2)并發標記(Concurrent Mark):并發標記所有存活對象。
(3)重新標記(Remark):暫停線程,處理并發標記期間新增的對象。
(4)并發清除(Concurrent Sweep):并發清除垃圾對象。 - 優點:低停頓時間。
- 缺點:
(1)內存碎片化(可能導致Full GC)。
(2)對CPU資源敏感。 - 命令行參數:
-XX:+UseConcMarkSweepGC
4. G1(Garbage-First)收集器(分區)
- 目標:兼顧吞吐量和低延遲,適用于大內存(>6GB)和多核CPU。
- 核心思想:
(1) 將堆內存劃分為多個Region(大小相等,1~32MB)。
(2) 優先回收垃圾最多的Region。 - 回收步驟:
(1)初始標記(Initial Mark):暫停線程,標記GC Roots。
(2)并發標記(Concurrent Mark):并發標記存活對象。
(3)最終標記(Final Mark):處理并發標記期間新增的對象。
(4)篩選回收(Live Data Counting and Evacuation):選擇回收價值高的Region進行回收。 - 優點:
可預測的停頓時間(通過 -XX:MaxGCPauseMillis 設置)。
避免內存碎片(回收時進行壓縮)。 - 缺點:
內存占用較高(維護Region狀態)。 - 命令行參數:
-XX:+UseG1GC
🧱 四、GC收集器對比總結

🔄 五、GC類型與觸發條件

🧪 六、常見GC異常與調優
1. 內存泄漏(Memory Leak)
- 原因:對象不再使用但無法被GC回收(如緩存未清理、監聽器未注銷)。
- 定位工具:
(1) MAT(Memory Analyzer):分析堆轉儲(heap dump)。
(1) VisualVM:實時監控內存使用情況。
(3) jmap + jhat:生成并分析堆轉儲。
2. 內存溢出(OutOfMemoryError)
- 常見類型:
- Java heap space:堆內存不足。
- GC overhead limit exceeded:GC頻繁且效率低。
- PermGen / Metaspace:方法區或元空間內存不足。
- 解決方法:
- 增加堆大小(-Xmx)。
- 調整元空間大小(-XX:MaxMetaspaceSize)。
- 優化代碼(減少對象創建、及時釋放資源)。
3. GC調優目標
目標 | 說明 |
---|
吞吐量(Throughput) | 單位時間內處理任務的效率(適合后臺計算任務) |
停頓時間(Pause Time) | 每次GC暫停的時間(適合Web服務) |
內存占用(Footprint) | 堆內存使用量(適合內存敏感場景) |
4. GC調優常用參數
參數 | 說明 |
---|
-Xms / -Xmx | 設置堆初始和最大大小(如 -Xms2g -Xmx4g) |
-XX:NewRatio | 新生代與老年代比例(默認1:2) |
-XX:SurvivorRatio | Eden與Survivor比例(默認8:1:1) |
-XX:MaxGCPauseMillis | G1收集器的目標停頓時間(默認200ms) |
-XX:G1HeapRegionSize | G1的Region大小(1~32MB) |
-XX:+PrintGCDetails | 打印詳細GC日志 |
-XX:+PrintGCDateStamps | 打印GC時間戳 |
-Xloggc:/path/to/gc.log | 輸出GC日志到文件 |
🧩 七、常見GC問題排查工具
工具 | 說明 |
---|
jstat | 實時監控GC狀態(如 jstat -gc 1234 1000 每秒輸出GC信息) |
jmap | 生成堆轉儲(jmap -dump:format=b,file=heap.bin 1234) |
jhat | 分析堆轉儲(jhat heap.bin) |
VisualVM | 圖形化監控JVM內存、線程、GC等 |
MAT(Memory Analyzer) | 分析堆轉儲,定位內存泄漏 |
GC | 日志分析工具 如 GCViewer、GCEasy、GCPlot |
📋 八、常見面試題及答案
1. CMS 和 G1 的區別?

2. G1為何適合大內存?
- 分區管理:將堆劃分為多個Region,可并行回收。
- 可預測停頓:通過 -XX:MaxGCPauseMillis 設置目標停頓時間。
- 避免碎片化:回收時進行壓縮(Evacuation階段)。
3. CMS的缺點?
- 內存碎片化:可能導致Full GC(標記-清除算法的缺點)。
- 并發階段耗CPU:并發標記和清除階段占用CPU資源。
- Concurrent Mode Failure:老年代空間不足導致并發失敗,退化為Serial Old收集器。
4. 如何選擇合適的GC收集器?

5. Full GC的觸發條件?
- 老年代空間不足。
- 方法區(元空間)內存不足。
- 調用 System.gc()(可禁用 -XX:+DisableExplicitGC)。
- 分配大對象(如大數組)。
6. 如何優化GC性能?
- 合理設置堆大小:避免頻繁GC。
- 避免內存泄漏:使用緩存時注意釋放。
- 選擇合適收集器:如G1適合大內存。
- 監控GC日志:分析停頓時間和頻率。
📚 九、GC調優實踐建議

? 十、總結:GC機制核心知識點

📄 十一、完整GC日志示例
2023-10-23T15:30:00.123+0800: [GC (Allocation Failure) [PSYoungGen: 131072K->15360K(157248K)] 131072K->15360K(503936K), 0.0123456 secs] [Times: user=0.05 sys=0.00, real=0.01 secs]
日志解析:
- GC類型:Allocation Failure(分配失敗觸發GC)。
- GC區域:PSYoungGen(Parallel Scavenge新生代)。
- 內存變化:131072K->15360K(回收后內存占用)。
- 耗時:0.0123456 secs(GC耗時)。
📌 十二、推薦學習資料
- 《深入理解 Java 虛擬機》(周志明)
- 《Java 性能調優指南》
- JVM 官方文檔:https://docs.oracle.com/en/java/javase/17/gctuning/
- GC日志分析工具:GCViewer、GCEasy、GCPlot
- JVM調優視頻教程(B站、慕課網、CSDN)