一、新生代与老年代垃圾回收器的组合
| 新生代回收器 |
老年代回收器 |
适用场景 |
JDK 默认版本 |
| Serial |
Serial Old |
单线程客户端应用、低资源环境 |
JDK 1.3~8(客户端模式) |
| ParNew |
CMS |
低延迟 Web 服务、响应优先系统 |
JDK 5~8(需手动启用) |
| Parallel Scavenge |
Parallel Old |
高吞吐量后台任务(计算密集型) |
JDK 7~8(服务端模式默认) |
| G1 |
G1 自身管理分代 |
大堆内存、低延迟、动态分代 |
JDK 9+(服务端模式默认) |
二、各组合核心特点
1. Serial + Serial Old
- 新生代(Serial):
- 单线程复制算法(Stop-The-World,STW)。
- 简单高效,无线程交互开销。
- 老年代(Serial Old):
- 适用场景:
- 客户端应用(如 Swing 桌面程序)、嵌入式设备。
- 缺点:STW 时间长,不适用于服务端大堆内存。
2. ParNew + CMS
- 新生代(ParNew):
- 多线程复制算法(STW),与 Serial 兼容。
- 老年代(CMS):
- 多线程并发标记-清除算法(Concurrent Mark Sweep)。
- 四阶段:初始标记(STW)→ 并发标记→ 重新标记(STW)→ 并发清除。
- 适用场景:
- Web 服务、API 服务器(追求低延迟,容忍内存碎片)。
- 缺点:CPU 敏感,内存碎片可能导致 Full GC 退化(需压缩)。
3. Parallel Scavenge + Parallel Old
- 新生代(Parallel Scavenge):
- 老年代(Parallel Old):
- 适用场景:
- 批处理、科学计算(如 Hadoop 离线任务)。
- 缺点:STW 时间不可控,不适合低延迟场景。
4. G1(Garbage-First)
- 分代管理:
- 逻辑分代:仍保留新生代(Eden/Survivor)和老年代(Old)。
- 物理划分:将堆划分为多个大小固定的 Region(1MB~32MB),动态分配为 Eden/Survivor/Old/Humongous(大对象区)。
- 回收机制:
- Young GC:回收新生代 Region(STW)。
- Mixed GC:同时回收新生代和部分老年代 Region(STW),基于停顿预测模型。
- Full GC:退化时触发(单线程整理,类似 Serial Old)。
- 特点:
- 低延迟:通过 Region 回收和停顿预测控制 STW 时间(默认 200ms)。
- 大堆友好:适合 4GB 以上堆内存。
- 内存整理:Mixed GC 阶段并行整理,减少碎片。
- 适用场景:
三、关于 G1 的疑问解答
Q: G1 没有老年代了吗?
A: 不是。G1 仍然有老年代,但分代方式与传统回收器不同:
- 逻辑分代保留:对象年龄(Age)达到阈值后晋升到老年代。
- 物理 Region 动态分配:老年代由多个 Region 组成,不要求连续内存。
- 混合回收(Mixed GC) :选择性回收高垃圾比例的老年代 Region,避免全堆扫描。
四、对比总结
| 回收器组合 |
吞吐量 |
延迟 |
内存碎片 |
适用堆大小 |
| Serial + Serial Old |
低 |
高 |
低 |
<100MB |
| ParNew + CMS |
中 |
低 |
高 |
2~4GB |
| Parallel Scavenge |
高 |
中 |
低 |
2~8GB |
| G1 |
中高 |
低 |
低 |
>4GB |
五、选择建议
- 小堆 & 客户端:Serial + Serial Old。
- 中等堆 & 低延迟:ParNew + CMS(JDK 8 及之前)。
- 大堆 & 高吞吐:Parallel Scavenge + Parallel Old(计算密集型)。
- 大堆 & 低延迟:G1(JDK 9+ 首选)或 ZGC/Shenandoah(超大堆+极低延迟)。