垃圾收集器发展历程
时间线
| 年份 | 收集器 | 特点 | 适用场景 |
|---|---|---|---|
| 1999 | Serial | 单线程 | 客户端 |
| 2002 | Parallel | 并行,高吞吐量 | 服务端 |
| 2004 | CMS | 并发,低延迟 | 互联网应用 |
| 2012 | G1 | 分区,可预测停顿 | 大内存应用 |
| 2018 | ZGC/Shenandoah | 超低延迟 | 大内存、低延迟要求 |
核心概念
并行(Parallel)vs 并发(Concurrent)
并行(Parallel):
- 多个GC线程同时工作
- 仍需Stop The World
- 缩短停顿时间
应用线程: ████████ [暂停] ████████
GC线程1: ▓▓▓▓▓
GC线程2: ▓▓▓▓▓
GC线程3: ▓▓▓▓▓
并发(Concurrent):
- GC线程与应用线程同时运行
- 减少Stop The World时间
- 实现更复杂
应用线程: ████████████████████████
GC线程: ░░░░░░░░░░░░░░░░░░░░░░░░
(大部分时间并发执行)
吞吐量 vs 低延迟
吞吐量优先(Throughput):
- 关注总体执行效率
- 适合后台计算、批处理
- 代表:Parallel Scavenge
低延迟优先(Low Latency):
- 关注单次停顿时间
- 适合Web应用、交互式应用
- 代表:CMS、G1、ZGC
权衡:
吞吐量 = 运行用户代码时间 / (运行用户代码时间 + GC时间)
例如:
· 100秒运行时间,GC耗时5秒 → 吞吐量 = 95%
· 低延迟可能牺牲吞吐量
收集器组合
经典组合(JDK 8)
新生代收集器 老年代收集器
┌─────────────┐ ┌──────────────┐
│ Serial │────────▶│ Serial Old │
└─────────────┘ └──────────────┘
↓
┌─────────────┐ ┌──────────────┐
│ ParNew │────────▶│ CMS │
└─────────────┘ └──────────────┘
↓
┌─────────────┐ ┌──────────────┐
│ Parallel │────────▶│ Parallel Old │
│ Scavenge │ └──────────────┘
└─────────────┘
┌────────────────────────────────────┐
│ G1收集器 │
│ (统一收集新生代和老年代) │
└────────────────────────────────────┘
┌────────────────────────────────────┐
│ ZGC / Shenandoah │
│ (低延迟收集器) │
└────────────────────────────────────┘
收集器对比
| 收集器 | 类型 | 算法 | 停顿时间 | 吞吐量 | 适用场景 |
|---|---|---|---|---|---|
| Serial | 新生代 | 复制 | 长 | 低 | 客户端 |
| ParNew | 新生代 | 复制 | 中 | 中 | 配合CMS |
| Parallel Scavenge | 新生代 | 复制 | 中 | 高 | 后台计算 |
| Serial Old | 老年代 | 标记-整理 | 长 | 低 | 客户端 |
| Parallel Old | 老年代 | 标记-整理 | 中 | 高 | 后台计算 |
| CMS | 老年代 | 标记-清除 | 短 | 中 | Web应用 |
| G1 | 全堆 | 标记-整理 + 复制 | 可控 | 高 | 大内存应用 |
| ZGC | 全堆 | 着色指针 | 极短 | 高 | 超大堆 |
| Shenandoah | 全堆 | 转发指针 | 极短 | 高 | 超大堆 |
选择建议
应用类型与收集器
1. 单CPU、小内存(<100MB)
-XX:+UseSerialGC
2. 多CPU、中等内存、吞吐量优先
-XX:+UseParallelGC
3. 多CPU、大内存、低延迟要求
# JDK 8
-XX:+UseConcMarkSweepGC
# JDK 9+
-XX:+UseG1GC # (默认)
4. 超大堆(>4GB)、极低延迟
# JDK 11+
-XX:+UseZGC
# JDK 12+
-XX:+UseShenandoahGC
总结
核心要点
- 并行:多线程GC,仍需STW;并发:GC与应用同时运行
- 吞吐量优先:Parallel;低延迟优先:CMS/G1/ZGC
- 发展趋势:单线程 → 并行 → 并发 → 低延迟
- 选择原则:根据应用特点、内存大小、延迟要求选择
参考资料
- 《深入理解Java虚拟机(第3版)》- 周志明
- HotSpot GC算法
下一篇预告:《Serial/Serial Old:单线程收集器》