CMS垃圾收集器和G1垃圾收集器优略对比

本文对比了CMS和G1两种垃圾收集器的特点。CMS以最短回收停顿时间为优化目标,采用标记-清除算法,适用于对响应时间要求高的应用场景。G1收集器针对服务端应用设计,通过并行与并发方式减少停顿时间,同时具备可预测的停顿时间特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  1、CMS收集器是一种以获取最短回收停顿时间为目标的收集器。基于“标记-清除”算法实现,它的运作过程如下:

1)初始标记 2)并发标记 3)重新标记 4)并发清除

 CMS是一款优秀的收集器,主要优点:并发收集、低停顿。

缺点:

1)CMS收集器对CPU资源非常敏感。在并发阶段,它虽然不会导致用户线程停顿,但是会因为占用了一部分线程而导致应用程序变慢,总吞吐量会降低。        

2)CMS收集器无法处理浮动垃圾,可能会出现“Concurrent Mode Failure(并发模式故障)”失败而导致Full GC产生。

浮动垃圾:由于CMS并发清理阶段用户线程还在运行着,伴随着程序运行自然就会有新的垃圾不断产生,这部分垃圾出现的标记过程之后,CMS无法在当次收集中处理掉它们,只好留待下一次GC中再清理。这些垃圾就是“浮动垃圾”。

3)CMS是一款“标记--清除”算法实现的收集器,容易出现大量空间碎片。当空间碎片过多,将会给大对象分配带来很大的麻烦,往往会出现老年代还有很大空间剩余,但是无法找到足够大的连续空间来分配当前对象,不得不提前触发一次Full GC。

2、G1收集器(Region小堆区)是一款面向服务端应用的垃圾收集器。G1具备如下特点:

1、并行于并发:G1能充分利用CPU、多核环境下的硬件优势,使用多个CPU(CPU或者CPU核心)来缩短stop-The-World停顿时间。部分其他收集器原本需要停顿java线程执行的GC动作,G1收集器仍然可以通过并发的方式让java程序继续执行。

2、分代收集:虽然G1可以不需要其他收集器配合就能独立管理整个GC堆,但是还是保留了分代的概念。它能够采用不同的方式去处理新创建的对象和已经存活了一段时间,熬过多次GC的旧对象以获取更好的收集效果。

3、空间整合:与CMS的“标记--清理”算法不同,G1从整体来看是基于“标记整理”算法实现的收集器;从局部上来看是基于“复制”算法实现的。

4、可预测的停顿:这是G1相对于CMS的另一个大优势,降低停顿时间是G1和CMS共同的关注点,但G1除了追求低停顿外,还能建立可预测的停顿时间模型,能让使用者明确指定在一个长度为M毫秒的时间片段内,

5、G1运作步骤:

1、初始标记;2、并发标记;3、最终标记;4、筛选回收

上面几个步骤的运作过程和CMS有很多相似之处。初始标记阶段仅仅只是标记一下GC Roots能直接关联到的对象,并且修改TAMS的值,让下一个阶段用户程序并发运行时,能在正确可用的Region中创建新对象,这一阶段需要停顿线程,但是耗时很短,并发标记阶段是从GC Root开始对堆中对象进行可达性分析,找出存活的对象,这阶段时耗时较长,但可与用户程序并发执行。而最终标记阶段则是为了修正在并发标记期间因用户程序继续运作而导致标记产生变动的那一部分标记记录,虚拟机将这段时间对象变化记录在线程Remenbered Set Logs里面,最终标记阶段需要把Remembered Set Logs的数据合并到Remembered Set Logs里面,最终标记阶段需要把Remembered Set Logs的数据合并到Remembered Set中,这一阶段需要停顿线程,但是可并行执行。最后在筛选回收阶段首先对各个Region的回收价值和成本进行排序,根据用户所期望的GC停顿时间来制定回收计划。

完整文档链接如下:

http://note.youdao.com/noteshare?id=c2cdce81a4c8d33a8b1c5285923fe311&sub=WEB1b923ae1e2931423f50f7012eb229d35

<think>我们正在对比Parallel OldCMS垃圾收集器。这两个都是老年代的收集器,通常与新生代的收集器搭配使用。下面从多个维度进行对比。</think>### Parallel Old 与 CMS 垃圾收集器深度对比 #### **核心设计目标对比** | **特性** | **Parallel Old** | **CMS (Concurrent Mark-Sweep)** | |------------------|--------------------------------------|---------------------------------------| | 设计目标 | 吞吐量先 | 低延迟先 | | 工作模式 | 并行STW压缩 | 并发标记+增量清理 | | 适用场景 | 后台计算、批处理 | Web应用、实时系统 | | JDK版本支持 | JDK 6u18+(默认老年代收集器) | JDK 1.4.2引入,JDK 14标记废弃 | --- #### **内存回收机制对比** **1. Parallel Old 回收过程(3阶段)** ```java // 伪代码展示Parallel Old工作流程 public void collect() { // 阶段1: 初始标记 (STW) stopTheWorld(); markRoots(); // 标记GC Roots直接引用 // 阶段2: 并发标记 resumeWorld(); concurrentMarking(); // 遍历对象图 // 阶段3: 最终标记+压缩 (STW) stopTheWorld(); remark(); // 处理漏标对象 slidingCompact(); // 滑动压缩整理内存 } ``` **2. CMS 回收过程(4阶段)** ```java // 伪代码展示CMS工作流程 public void collect() { // 阶段1: 初始标记 (STW) stopTheWorld(); markRoots(); // 阶段2: 并发标记 resumeWorld(); concurrentMarking(); // 阶段3: 重新标记 (STW) stopTheWorld(); remark(); // 增量更新/三色标记修正 // 阶段4: 并发清除 resumeWorld(); concurrentSweep(); // 不压缩内存 } ``` --- #### **关键性能指标对比** | **指标** | Parallel Old | CMS | |------------------|----------------------------------|---------------------------------| | **吞吐量** | 高(目标80%+) | 中低(并发线程占用CPU) | | **暂停时间** | 长(压缩阶段STW) | 短(仅初始/重新标记STW) | | **内存碎片** | 无(压缩整理) | 严重(不压缩) | | **内存占用** | 低 | 高(需预留空间应对并发失败) | | **触发条件** | 老年代满(Full GC) | 老年代阈值(默认68%) | --- #### **内存碎片处理对比** **Parallel Old 压缩算法** ```java // 滑动压缩伪代码 void slidingCompact() { // 步骤1: 计算对象最终地址 for (Object obj : heap) { if (isMarked(obj)) { newAddress = calculateNewAddress(obj); setForwardingAddress(obj, newAddress); } } // 步骤2: 更新引用关系 for (Object obj : heap) { if (isMarked(obj)) { updateReferences(obj); // 修正所有引用指向新地址 } } // 步骤3: 移动对象 for (Object obj : heap) { if (isMarked(obj)) { moveObject(obj, getForwardingAddress(obj)); } } } ``` **CMS 碎片问题解决方案** - **临时方案**:`-XX:+UseCMSCompactAtFullCollection`(Full GC时压缩) - **永久方案**:切换到G1/CMS(JDK9+废弃CMS) --- #### **并发失败处理对比** **1. Parallel Old 无并发失败风险** - 始终STW执行,无并发冲突 **2. CMS 并发失败处理流程** ```mermaid graph LR A[并发模式失败] --> B{老年代空间是否足够} B -->|不足| C[触发Serial Old收集器] C --> D[Full GC STW暂停] D --> E[内存压缩] ``` **触发条件**: - 并发清理期间新对象分配速度 > 清理速度 - 老年代碎片无法分配大对象 --- #### **配置参数对比** | **参数** | Parallel Old | CMS | |-----------------------------------|----------------------------------|---------------------------------| | 启用参数 | `-XX:+UseParallelOldGC` | `-XX:+UseConcMarkSweepGC` | | 并行线程数 | `-XX:ParallelGCThreads=N` | `-XX:ParallelCMSThreads=N` | | 最大暂停时间目标 | `-XX:MaxGCPauseMillis=ms` | `-XX:MaxGCPauseMillis=ms` | | 老年代触发阈值 | 无 | `-XX:CMSInitiatingOccupancyFraction=68` | | 碎片整理 | 自动 | `-XX:+UseCMSCompactAtFullCollection` | | 增量模式 | 不支持 | `-XX:+CMSIncrementalMode`(已废弃) | --- #### **生产环境选型指南** **选择 Parallel Old 当**: 1. 应用对吞吐量要求 > 延迟要求 2. 堆内存 < 8GB 3. 对象生命周期长,老年代占比高 **选择 CMS 当**: 1. 要求暂停时间 < 200ms 2. CPU资源充足(至少4核) 3. 堆内存 < 16GB(避免并发失败) **典型案例**: ```java // 电商交易系统(低延迟) -Djava.awt.headless=true -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=75 -XX:+CMSParallelRemarkEnabled // 数据分析系统(高吞吐) -XX:+UseParallelGC -XX:+UseParallelOldGC -XX:ParallelGCThreads=8 -XX:MaxGCPauseMillis=500 ``` --- #### **升级替代方案** | **场景** | **JDK 8推荐** | **JDK 11+推荐** | |------------------------|----------------------|----------------------| | 替代Parallel Old | G1 (`-XX:+UseG1GC`) | ZGC (`-XX:+UseZGC`) | | 替代CMS | G1 | Shenandoah (`-XX:+UseShenandoahGC`) | | 大堆内存(>32GB) | G1 | ZGC/Shenandoah | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值