垃圾回收器选择
约 1103 字大约 4 分钟
2025-08-29
垃圾回收器分类概述
- 新生代收集器:Serial、ParNew、Parallel Scavenge
- 老年代收集器:Serial Old、Parallel Old、CMS
- 整堆收集器(或分代、不分代):G1、ZGC、Shenandoah
各垃圾回收器特点
串行垃圾回收器 (Serial GC / Serial Old)
- 特点:单线程执行垃圾回收,在进行垃圾回收时会暂停所有应用线程(Stop-The-World, STW)。
- 适用场景:适用于单核 CPU 环境或内存较小的应用(如客户端模式下的 JVM),因为其实现简单,开销较小。不适合多核环境和大内存应用,因为 STW 时间较长。
并行垃圾回收器 (Parallel Scavenge / Parallel Old / ParNew)
- 特点:多线程执行垃圾回收,在进行垃圾回收时也会暂停所有应用线程。Parallel Scavenge 关注吞吐量,ParNew 是 Serial 的多线程版本,通常与 CMS 配合使用。
- 适用场景:适用于多核 CPU 环境。更侧重于达到高吞吐量(Throughput),适合批处理、后台作业等对暂停时间不敏感的应用。
并发标记扫描垃圾回收器 (CMS Garbage Collector)
- 特点:以最小化 STW 时间为目标,采用并发标记和并发清除阶段,使得大部分垃圾回收工作可以与应用线程一起执行。
- 优点:低延迟,适合对响应时间有较高要求的应用。
- 缺点:容易产生内存碎片,当碎片过多时可能触发 Full GC 进行碎片整理,此时会导致较长的 STW。此外,CMS 在并发执行时会占用一部分 CPU 资源,对吞吐量有一定影响。
G1 垃圾回收器 (G1 Garbage Collector)
- 特点:JDK 7 中推出,JDK 9 中成为默认垃圾回收器。它将堆内存划分为多个大小相等的区域(Region),以增量方式进行回收。具备可预测的暂停时间模型,允许用户设置期望的 STW 目标。
- 适用场景:适用于大内存(通常建议 4GB 以上)和多核 CPU 环境。旨在替代 CMS,提供更低的暂停时间和更好的吞吐量平衡。适合大数据量、需要软实时响应的应用。
ZGC (The Z Garbage Collector) / Shenandoah GC
- 特点:ZGC (JDK 11 推出)、Shenandoah (JDK 12 推出) 是超低延迟的垃圾回收器。它们的目标是将 STW 时间控制在极低的水平(通常在 10ms 以下),即使在处理 TB 级别的堆内存时也能保持低延迟。
- 适用场景:适用于对响应时间有极高要求的应用,如金融交易系统、大数据实时分析等。
- 限制:目前只支持较新的 JDK 版本,且可能存在一些不成熟的特性或配置复杂度。
垃圾回收器选择依据
综合以上特点,选择垃圾回收器时可以遵循以下原则:
根据硬件资源判断:
- 单核 CPU 或内存较小 (MB 级别):选择 Serial GC,简单高效。
- 多核 CPU 且内存适中 (GB 级别):可以考虑 Parallel 系列(追求高吞吐量)或 CMS(追求低延迟)。
根据业务类型和性能目标判断:
- 追求高吞吐量 (Throughput):如果应用是批处理任务、数据分析等后台作业,对单次停顿时间不敏感,更关注单位时间内完成的工作量,则选择 Parallel Scavenge 和 Parallel Old 组合。
- 追求低延迟 (Low Latency):如果应用是实时交易系统、Web 服务等需要快速响应的应用,对 STW 时间非常敏感,则优先选择 CMS、G1、ZGC 或 Shenandoah。
根据堆内存大小判断:
- 小堆内存 (几百 MB 到 1-2 GB):Serial、Parallel、CMS 都能很好地工作。
- 中大堆内存 (4GB 到几十 GB):G1 是一个很好的通用选择,能够平衡吞吐量和延迟。
- 超大堆内存 (几十 GB 到 TB 级别):ZGC 或 Shenandoah 是最佳选择,它们旨在解决超大堆内存下的超低延迟问题。
根据 JDK 版本判断:
- JDK 8 及以前:Parallel 系列是默认的,CMS 也是常用选择。G1 在 JDK 7 引入,JDK 8 中逐渐成熟。
- JDK 9 及以后:G1 成为默认垃圾回收器。
- JDK 11 及以后:可以考虑使用 ZGC。
- JDK 12 及以后:可以考虑使用 Shenandoah。