收集器分代佈局
JVM 堆劃分為新生代(Young)與老年代(Old)。不同收集器作用於不同代,且存在配對關係:
| 新生代收集器 | 老年代收集器 | 可搭配 |
| Serial | Serial Old | ✓ |
| ParNew | CMS / Serial Old | ✓ |
| Parallel Scavenge | Parallel Old | ✓ |
| G1 | G1 (整堆) | 獨立 |
七大經典收集器深度解析
1. Serial 收集器
- 單線程、Stop-The-World (STW)
- 新生代:複製算法;老年代:標記-整理
- Client 模式默認,單 CPU 環境最高效(無線程切換開銷)
2. ParNew 收集器
- Serial 的多線程版,同樣用複製算法
- 唯一能與 CMS 搭配的新生代收集器
- 多 CPU 時優於 Serial,但單 CPU 因線程管理反而較慢
3. Parallel Scavenge 收集器
- 新生代、複製算法、多線程
- 目標:可控吞吐量 = 用戶代碼時間 / (用戶代碼時間 + GC 時間)
- 自適應調節策略(
-XX:+UseAdaptiveSizePolicy)自動調整新生代大小、晉升閾值
- 適合後台計算、批處理類無交互應用
- 不能與 CMS 搭配
4. Serial Old 收集器
- Serial 老年代版,單線程、標記-整理、STW
- Client 模式默認老年代收集器
- 也作為 CMS 失敗時的備選(Concurrent Mode Failure)
5. Parallel Old 收集器
- Parallel Scavenge 老年代版,多線程、標記-整理
- JDK 1.6+ 提供,配合 Parallel Scavenge 組成「吞吐量優先」組合
6. CMS 收集器
- 目標:最短停頓時間,老年代、標記-清除
- 四階段:
① 初始標記 (STW) - 僅標記 GC Roots 直達對象,極快
② 並發標記 - GC Roots Tracing,耗時長但與用戶線程並發
③ 重新標記 (STW) - 修正並發階段變動,較短
④ 並發清除 - 與用戶線程並發
- 優點:低停頓、並發收集
- 缺點:
① CPU 敏感(佔用核心導致應用變慢)
② 無法處理浮動垃圾(並發產生的新垃圾,下次 GC 清理)
③ 內存碎片(標記-清除不整理),大對象分配困難觸發 Full GC
7. G1 (Garbage-First) 收集器
- JDK 1.7+,面向服務端、大堆(>4GB)、多核
- 不再物理劃分代,堆劃分為多個大小固定(1-32MB)Region
- 每個 Region 動態扮演 Eden/Survivor/Old 角色
- Remembered Set (RSet) 記錄跨 Region 引用,實現 Region 級並行回收
- 四階段:初始標記(STW) → 並發標記 → 最終標記(STW,多線程) → 篩選回收(STW,按回收價值優先級)
- 核心優勢:
① 可預測停頓:指定目標停頓時間,優先回收垃圾最多 Region
② 無碎片:基於標記-整理,Region 間復制壓縮
③ 大堆友好:增量式回收,避免全堆掃描
關鍵概念辨析
| 概念 | Serial/Parallel | CMS/G1 |
| 並行 | 多 GC 線程同時工作,用戶線程暫停 | GC 線程與用戶線程同時運行 |
| 目標 | 高吞吐量 | 低停頓 |
| 算法 | 複製/標記-整理 | 標記-清除/標記-整理 |
選型建議
- 單核/小堆/Client:
-XX:+UseSerialGC
- 多核/批處理/高吞吐:
-XX:+UseParallelGC (+ UseParallelOldGC)
- 多核/交互應用/低延遲:
-XX:+UseParNewGC -XX:+UseConcMarkSweepGC
- 大堆(>6GB)/多核/可預測停頓:
-XX:+UseG1GC