Java垃圾回收算法与选择
不同垃圾回收器有不同特点,需根据应用场景选择合适的收集器。
GC算法对比
| 算法 | 特点 | 适用场景 |
|---|---|---|
| 标记-清除 | 简单但有碎片 | CMS(老年代) |
| 标记-复制 | 无碎片但空间利用率低 | 年轻代 |
| 标记-整理 | 无碎片但移动成本高 | Serial Old、Parallel Old |
常见垃圾收集器
年轻代收集器
| 收集器 | 算法 | 特点 | 适用场景 |
|---|---|---|---|
| Serial | 复制 | 单线程,STW | 单CPU、小堆 |
| ParNew | 复制 | 多线程版Serial | 配合CMS |
| Parallel Scavenge | 复制 | 关注吞吐量 | 后台计算任务 |
老年代收集器
| 收集器 | 算法 | 特点 | 适用场景 |
|---|---|---|---|
| Serial Old | 标记-整理 | 单线程 | 小堆、CMS后备 |
| Parallel Old | 标记-整理 | 多线程,吞吐量优先 | 配合Parallel Scavenge |
| CMS | 标记-清除 | 并发收集,低延迟 | 交互式应用 |
G1收集器
| 特性 | 说明 |
|---|---|
| 分区模型 | 堆划分为多个Region |
| 可预测停顿 | 设置目标停顿时间 |
| 并发标记 | 与应用并发执行 |
| 无碎片 | 复制算法整理 |
| 适用堆 | > 4GB |
收集器选择策略
按应用类型选择
Bash
┌─────────────────────────────────────┐
│ 应用类型判断 │
├─────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐│
│ │ 交互式应用 │ │ 后台任务 ││
│ │ (Web服务) │ │ (批处理) ││
│ └ │ │ ││
│ │ 关注延迟 │ │ 关注吞吐量 ││
│ │ │ │ ││
│ │ CMS / G1 │ │ Parallel ││
│ └─────────────┘ └─────────────┘│
│ │
│ ┌─────────────────────────────┐ │
│ │ 大堆应用 (>4GB) │ │
│ │ │ │
│ │ G1 / ZGC │ │
│ └─────────────────────────────┘ │
│ │
└─────────────────────────────────────┘
按堆大小选择
| 堆大小 | 推荐收集器 |
|---|---|
| < 100MB | Serial |
| 100MB - 4GB | Parallel / CMS |
| > 4GB | G1 |
| > 16GB | ZGC / Shenandoah |
按JDK版本选择
| JDK版本 | 默认收集器 | 推荐升级 |
|---|---|---|
| JDK 8 | Parallel | CMS/G1(低延迟) |
| JDK 11 | G1 | ZGC(大堆) |
| JDK 17 | G1 | ZGC(生产可用) |
各收集器配置
Serial收集器
Bash
-XX:+UseSerialGC
# 适用:单核CPU、小堆、客户端应用
Parallel收集器
Bash
-XX:+UseParallelGC
-XX:+UseParallelOldGC
# 吞吐量参数
-XX:MaxGCPauseMillis=200 # 最大停顿时间
-XX:GCTimeRatio=99 # GC时间占比(1/(1+99)=1%)
# 适用:后台计算、批处理任务
CMS收集器
Bash
-XX:+UseConcMarkSweepGC
-XX:+UseParNewGC # 年轻代用ParNew
# CMS参数
-XX:CMSInitiatingOccupancyFraction=70 # 触发阈值
-XX:+UseCMSCompactAtFullCollection # Full GC时压缩
-XX:CMSFullGCsBeforeCompaction=0 # 每次都压缩
# 适用:Web应用、交互式系统、低延迟需求
G1收集器
Bash
-XX:+UseG1GC
# G1参数
-XX:MaxGCPauseMillis=200 # 目标停顿时间
-XX:G1HeapRegionSize=4m # Region大小(1-32MB)
-XX:InitiatingHeapOccupancyPercent=45 # 触发并发标记
# 适用:大堆应用、低延迟需求
ZGC收集器(JDK 15+)
text
-XX:+UseZGC
# ZGC参数
-XX:ZCollectionInterval=5 # 主动GC间隔(秒)
# 适用:超大堆(>16TB)、极低延迟(<10ms)
CMS详解
CMS工作流程
text
┌─────────────────────────────────────────────┐
│ CMS流程 │
├─────────────────────────────────────────────┤
│ │
│ 1.初始标记(STW) ─→ 标记GC Roots直接关联对象 │
│ │
│ 2.并发标记 ─→ 并发标记所有可达对象 │
│ │
│ 3.重新标记(STW) ─→ 修正并发期间的变动 │
│ │
│ 4.并发清除 ─→ 并发清除标记对象 │
│ │
│ (可选)并发重置 ─→ 重置CMS状态 │
│ │
└─────────────────────────────────────────────┘
CMS优缺点
| 优点 | 缺点 |
|---|---|
| 低延迟 | 有内存碎片 |
| 并发收集 | CPU敏感 |
| 适用交互应用 | 浮动垃圾问题 |
| 可能触发Full GC |
G1详解
G1分区模型
text
┌─────────────────────────────────────┐
│ G1堆分区 │
├─────────────────────────────────────┤
│ ┌─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┐│
│ │E│E│S│S│O│O│O│H│H│ │ │ │ │ │ │ ││
│ └─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┘│
│ │
│ E=Eden, S=Survivor │
│ O=Old, H=Humongous(大对象) │
│ 空白=空闲Region │
└─────────────────────────────────────┘
G1工作模式
| 模式 | 触发条件 | 特点 |
|---|---|---|
| Young GC | Eden区满 | 只收集年轻代 |
| Mixed GC | 并发标记后 | 年轻代+部分老年代 |
| Full GC | 内存不足 | 单线程STW |
收集器演进趋势
text
Serial → Parallel → CMS → G1 → ZGC/Shenandoah
方向:
1. 单线程 → 多线程 → 并发
2. 关注吞吐 → 关注延迟
3. 整堆收集 → 分区收集
4. STW → 并发 → 几乎无停顿
注意事项
CMS已废弃(JDK14),建议使用G1
G1适合大堆,小堆可能不如Parallel
ZGC在JDK15+生产可用,延迟<10ms
选择收集器需考虑CPU核数和堆大小
调优应从监控数据出发,而非盲目设置
要点总结
- 交互应用选CMS/G1,后台任务选Parallel
- 小堆(<100MB)用Serial,大堆(>4GB)用G1
- JDK 11+默认G1,大堆可升级ZGC
- CMS低延迟但有碎片,G1分区可预测停顿
- 收集器选择需结合应用类型、堆大小、JDK版本
📝 发现内容有误?点击此处直接编辑