CMS垃圾回收器并发标记、内存碎片、浮动垃圾、优缺点总结

CMS垃圾收集器的浮动垃圾

  1. 并发标记阶段本来可达的对象,由于用户线程的作用变得不可达了,即产生新的垃圾对象,CMS将无法对这些垃圾对象进行标记,最终导致这些新产生的垃圾对象没有被及时回收。【重新标记阶段只会利用增量更新来解决因并发标记阶段产生的对象消失问题,而浮动垃圾的产生原因是因为已经被GC线程被标记为黑色了,但用户线程接着又取消了对它的所有引用,但是黑色对象并不会被重新扫描,所以重新标记是找不到浮动垃圾的,就算能解决,并发清理阶段一样会产生浮动垃圾,而并发清理已经是最后一个阶段了,所以浮动垃圾只能下次垃圾回收的时候才能被回收
  2. 在并发清理阶段也可能产生新的垃圾,也被称为浮动垃圾。

        重新标记阶段主要是对并发标记阶段所有标记的非可达对象进行标记,标记出在并发标记new的新对象,在初始标记阶段和并发标记阶段没有将其标记为可达的,从而产生致命性错误。

 CMS垃圾收集器的优缺点

优点:并发收集、低延迟。

缺点:会产生内存碎片、CMS收集器对CPU资源敏感、CMS收集器无法处理浮动垃圾

  • 会产生内存碎片:,导致并发清除后,用户线程可用的空间不足。在无法分配大对象的情况下,不得不提前触发Full GC。
  • CMS收集器对CPU资源非常敏感:。在并发阶段,它虽然不会导致用户停顿,但是会因为占用了一部分线程而导致应用程序变慢,总吞吐量会降低。
  • CMS收集器无法处理浮动垃圾。可能出现"Concurrent Mode Failure"失败而导致另一次Full GC的产生。在并发标记阶段由于程序的工作线程和垃圾收集线程是同时运行或者交叉运行的,那么在并发标记阶段如果产生新的垃圾对象,CMS将无法对这些垃圾对象进行标记,最终会导致这些新产生的垃圾对象没有被及时回收,从而只能在下一次执行GC时释放这些之前未被回收的内存空间。

 CMS浮动垃圾引起的问题

        在并发标记阶段以及并发清理阶段可能产生一定的浮动垃圾,CMS对这部分垃圾不进行处理的,只会等下一次GC的时候处理。 这就会产生一个问题,当老年代的内存空间存放不下这些浮动垃圾时,就会导致并发失败。这时候虚拟机将不得不启动后备预案:冻结用户线程的执行,临时启用Serial Old收集器来重新进行老年代的垃圾收集,但这样停顿时间就很长了。

CMS内存碎片引起的问题

        CMS是一款基于“标记-清除”算法实现的收集器,这意味着收集结束时会有大量空间碎片产生。空间碎片过多时,将会给大对象分配带来很大麻烦,往往会出现老年代还有很多剩余空间,但就是无法找到足够大的连续空间来分配当前对象,而不得不提前触发一次Full GC的情况。

  1. CMS存在一个默认的参数 “-XX:+UseCMSCompactAtFullCollection”,意思是在Full GC之后再次STW,停止工作线程,整理内存空间,将存活的对象移到一边。
  2. 还有一个参数是“-XX:+CMSFullGCsBeforeCompaction”,表示在进行多少次Full GC之后进行内存碎片整理,默认为0,即每次Full GC之后都进行内存碎片整理。

CMS并发标记阶段是否会标记所有的对象

        不会,CMS会内置记录在并发标记期间那些被新建的对象或者有变动的对象,因此重新标记阶段不需要再重新标记所有对象,只对并发标记阶段改动过的对象做标记即可。

  • 新建的对象。
  • 有变动的对象,这里的有变动指的仅仅是原来不可达但是由于并发标记阶段线程之间的作用使不可达变为可达,此时在重新标记阶段需要对其标记,防止GC回收造成严重错误。
    • 为什么不对原本可到->不可达的对象进行标记,此时需要从GCroot重新开始依次查找标记,相当于返回了并发标记,不符合CMS设计理念。

参考链接

CMS垃圾收集器:重新标记和浮动垃圾的思考_重新标记阶段为什么不能处理浮动垃圾-优快云博客 CMS的特点与弊端分析 - 简书

<think>好的,用户现在想了解CMS垃圾回收器优缺点,而且他们之前已经讨论过CMS的核心参数。我需要结合之前的对话和用户提供的引用内容来回答问题。 首先,用户提到的引用[2]和[3]都详细说明了CMS的缺点,比如内存碎片、CPU敏感和浮动垃圾的问题。而优点方面,引用[2]提到CMS并发阶段不会导致用户停顿,所以低延迟应该是一个主要优点。用户可能是在优化Java应用时遇到停顿问题,所以需要权衡CMS优缺点。 然后,用户之前的问题是关于CMS核心参数的,比如并发线程数、触发阈值等,这些参数如何影响性能。所以在回答优缺点时,可以关联到这些参数设置,比如CMSInitiatingOccupancyFraction的设置影响Full GC的频率。 另外,用户可能没有明确说明他们的应用场景,但根据之前讨论的CMS参数,可能是在处理需要低延迟的应用,比如Web服务。需要指出CMS适合这种场景,但也要提醒内存碎片和CPU资源的问题。 需要注意的是,用户提供的引用中有错误,比如引用[1]是关于Java GC的基础知识,而用户的问题是关于CMS的,所以主要参考引用[2]和[3]。要确保正确引用这些内容,比如引用[3]提到的触发阈值设置,引用[2]提到的并发模式失败和浮动垃圾。 最后,生成相关问题时,要考虑用户可能进一步想知道如何调优CMS,或者与其他收集器的比较,比如G1。确保问题有针对性,帮助用户深入理解。</think>### CMS垃圾回收器的核心优缺点解析 --- #### **一、CMS垃圾回收器的核心优点** 1. **低延迟的核心设计** - **并发标记与清除**:CMS(Concurrent Mark-Sweep)通过并发执行垃圾回收阶段(标记、清除),**大幅减少应用停顿时间**(STW时间)。例如,在初始标记(Initial Mark)和重新标记(Remark)阶段仅短暂暂停用户线程[^2][^3]。 - **适用场景**:适合对响应时间敏感的应用(如Web服务、实时系统),避免长时间停顿影响用户体验[^2]。 2. **增量式垃圾回收** - **分阶段处理**:CMS将回收过程分解为多个阶段(如并发标记并发清除),允许垃圾回收与用户线程交替执行,**减少单次停顿的持续时间**[^3]。 3. **老年代优先回收** - **针对性优化**:CMS专为老年代设计,通过并发清除减少大对象回收的延迟,避免频繁Full GC对性能的冲击[^2]。 --- #### **二、CMS垃圾回收器的核心缺点** 1. **内存碎片问题** - **标记-清除算法的固有缺陷**:CMS不会压缩内存空间,长期运行后可能产生内存碎片,导致无法分配连续大对象(如数组),最终**被迫触发Full GC**(如Serial Old GC)进行压缩,引发长时间停顿[^2][^3]。 - **解决方案**:通过参数`-XX:+UseCMSCompactAtFullCollection`(默认启用)在Full GC时进行碎片整理,但会延长Full GC时间[^3]。 2. **CPU资源敏感** - **并发阶段的资源竞争**:在并发标记和清除阶段,CMS会占用部分CPU资源(默认启动`(CPU核数 + 3)/4`个线程[^2]),可能导致**应用吞吐量下降**(如高并发计算任务性能降低)。 - **调优建议**:通过`-XX:ConcGCThreads`手动限制并发线程数,平衡GC与应用性能[^2]。 3. **浮动垃圾处理缺陷** - **并发标记阶段的遗漏**:在并发标记过程中,用户线程可能产生新的垃圾浮动垃圾),CMS无法实时回收,需依赖下一次GC。若浮动垃圾累积过快,可能触发**Concurrent Mode Failure**(并发模式失败),强制启动Full GC[^3]。 - **参数调优**:通过`-XX:CMSInitiatingOccupancyFraction`(默认92%)调整触发CMS GC的老年代使用率阈值。阈值过低会导致频繁CMS GC,过高则增加并发模式失败风险[^3]。 4. **无法处理元空间溢出** - **局限性**:CMS仅管理堆内存(新生代、老年代),元空间(Metaspace)溢出仍需依赖Full GC或元空间扩容[^2]。 --- #### **三、CMS与其他GC的对比** | **特性** | **CMS** | **Parallel Old** | **G1** | |------------------------|--------------------------------|-------------------------------|-------------------------------| | **设计目标** | 低延迟 | 高吞吐量 | 平衡延迟与吞吐量 | | **内存碎片** | 严重 | 无(压缩算法) | 可控(Region分区) | | **适用场景** | 老年代低延迟需求 | 批处理任务 | 大堆内存、混合回收 | | **Full GC触发条件** | 并发模式失败/内存碎片 | 内存不足 | 疏散失败/元空间不足 | --- #### **四、CMS调优关键参数** 1. **并发线程控制** ```bash -XX:ConcGCThreads=2 # 限制并发标记线程数 ``` 2. **触发阈值优化** ```bash -XX:CMSInitiatingOccupancyFraction=75 # 老年代使用率75%时触发CMS GC ``` 3. **碎片整理策略** ```bash -XX:+UseCMSCompactAtFullCollection # Full GC时压缩内存 -XX:CMSFullGCsBeforeCompaction=5 # 每5次Full GC后压缩一次 ``` --- ### 相关问题 1. **如何通过JVM参数避免CMS的Concurrent Mode Failure?** (需结合`CMSInitiatingOccupancyFraction`与堆内存监控工具分析)[^3] 2. **CMS与G1垃圾回收器的性能差异在哪些场景下最明显?** (对比大堆内存、高并发请求等场景)[^2] 3. **CMS浮动垃圾如何影响Java应用的稳定性?** (分析并发模式失败的实际案例与调优方法)[^2][^3]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值