G1回收器和CMS回收器都是Java垃圾回收器的常见类型,但它们在设计目标、工作原理和性能特点等方面存在显著区别,以下是具体对比:
工作原理
- CMS回收器:
- 采用标记-清除算法,主要针对老年代进行垃圾回收。
- 回收过程分为多个阶段:初始标记(STW)、并发标记、预清理、可终止的预清理、重新标记(STW)、并发清理和重置。
- 并发标记阶段允许垃圾回收线程与用户线程同时运行,减少停顿时间。
- G1回收器:
- 将堆内存划分为多个大小相等的区域(Region),每个Region可以是Eden区、Survivor区或Old区。
- 回收过程分为初始标记(STW)、并发标记、最终标记(STW)和筛选回收(STW)。
- 在老年代回收时采用标记-整理算法,避免内存碎片化;年轻代回收则采用复制算法。
内存管理与碎片处理
- CMS回收器:
- 由于采用标记-清除算法,回收后不压缩内存,容易产生内存碎片。
- 需要依赖
UseCMSCompactAtFullCollection
参数手动触发Full GC来整理碎片。
- G1回收器:
- 通过复制算法整理内存,回收后自动整理Region,避免碎片问题。
- 优先回收垃圾比例高的Region,优化回收效率。
性能特点
- 停顿时间:
- CMS回收器:停顿时间较短,主要集中在初始标记和重新标记阶段,适合对延迟敏感的应用。
- G1回收器:通过
MaxGCPauseMillis
参数设定目标停顿时间,通常在10-200ms之间,停顿时间可控。
- 吞吐量:
- CMS回收器:并发标记和清理阶段会占用约25%-30%的CPU资源,导致吞吐量较低。
- G1回收器:通过Region分区和并行回收优化吞吐量,吞吐量较高。
- 内存占用:
- CMS回收器:内存占用较低,仅需少量元数据。
- G1回收器:需要维护Region元数据,占用约10%-20%的额外内存。
适用场景
- CMS回收器:
- 适用于对延迟敏感的老年代回收,如实时交易系统。
- JDK 9起被标记为废弃,JDK 14中彻底移除,仅适用于老旧系统维护。
- G1回收器:
- 适用于大堆内存(4GB以上)且需平衡吞吐量与延迟的场景,如大数据处理、服务端应用。
- 是JDK 9+的默认垃圾收集器,适合长期运行项目。
其他区别
- 并发与并行:
- CMS回收器:主要是并发回收,即垃圾回收线程与用户线程同时运行。
- G1回收器:既支持并发回收,也支持并行回收,可以利用多核CPU加速垃圾回收。
- 记忆集维护:
- CMS回收器:基于粗粒度的卡表,适合简单的跨代引用场景。
- G1回收器:基于精细粒度的卡表,维护更复杂,但能更精确地记录跨Region的引用。