深入探索JVM垃圾收集器 — 经典垃圾收集器之CMS收集器

CMS收集器是Java的一种垃圾收集器,专注于缩短回收停顿时间,适合互联网应用。它包括初始标记、并发标记、重新标记和并发清除四个步骤,其中并发标记和并发清除阶段与用户线程并发执行。CMS的主要优点是并发收集和低停顿,但也存在对处理器资源敏感、无法处理浮动垃圾可能导致Full GC以及产生内存碎片等问题。可以通过调整CMSInitiatingOccupancyFraction参数优化触发阈值,使用CMSCollectBeforeAllocation参数避免并发失败,以及通过CMSFullGCsBeforeCompaction参数进行碎片整理。

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

 

CMS收集器(基于 标记-清除算法 老年代 )

CMSConcurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器。

目前很 大一部分的Java应用集中在互联网网站或者基于浏览器的B/S系统的服务端上,这类应用通常都会较为 关注服务的响应速度希望系统停顿时间尽可能短,以给用户带来良好的交互体验。CMS收集器就非 常符合这类应用的需求。

CMS运作过程:四个步骤

1)初始标记(CMS initial mark)

2)并发标记(CMS concurrent mark)

3)重新标记(CMS remark)

4)并发清除(CMS concurrent sweep)

 

其中初始标记、重新标记这两个步骤仍然需要“Stop The World”。初始标记仅仅只是标记一下GC Roots能直接关联到的对象,速度很快;并发标记阶段就是从GC Roots的直接关联对象开始遍历整个对 象图的过程,这个过程耗时较长但是不需要停顿用户线程,可以与垃圾收集线程一起并发运行;而重 新标记阶段则是为了修正并发标记期间,因用户程序继续运作而导致标记产生变动的那一部分对象的 标记记录(详见3.4.6节中关于增量更新的讲解),这个阶段的停顿时间通常会比初始标记阶段稍长一 些,但也远比并发标记阶段的时间短;最后是并发清除阶段,清理删除掉标记阶段判断的已经死亡的 对象,由于不需要移动存活对象,所以这个阶段也是可以与用户线程同时并发的。

由于在整个过程中耗时最长的并发标记和并发清除阶段中,垃圾收集器线程都可以与用户线程一 起工作,所以从总体上来说,CMS收集器的内存回收过程是与用户线程一起并发执行的。

CMS是一款优秀的收集器,它最主要的

优点:并发收集、低停顿,一些官 方公开文档里面也称之为“并发低停顿收集器”(Concurrent Low Pause Collector)。

缺点:

1.首先,CMS收集器对处理器资源非常敏感。事实上,面向并发设计的程序都对处理器资源比较敏 感。在并发阶段,它虽然不会导致用户线程停顿,但却会因为占用了一部分线程(或者说处理器的计 算能力)而导致应用程序变慢,降低总吞吐量。

2.CMS收集器无法处理“浮动垃圾”(Floating Garbage),有可能出现“Con-current Mode Failure”失败进而导致另一次完全“Stop The World”的Full GC的产生。

“浮动垃圾”在CMS的并发标记和并发清理阶 段,用户线程是还在继续运行的,程序在运行自然就还会伴随有新的垃圾对象不断产生,但这一部分 垃圾对象是出现在标记过程结束以后,CMS无法在当次收集中处理掉它们,只好留待下一次垃圾收集 时再清理掉。这一部分垃圾就称为“浮动垃圾”。

在JDK 5的默认设置下,CMS收集器当老年代使用了68%的空间后就会被激活,这是一个偏保守的设置,如果 在实际应用中老年代增长并不是太快,可以适当调高参数-XX:CMSInitiatingOccu-pancyFraction的值 来提高CMS的触发百分比,降低内存回收频率,获取更好的性能。

到了JDK 6时,CMS收集器的启动 阈值就已经默认提升至92%。但这又会更容易面临另一种风险:要是CMS运行期间预留的内存无法满 足程序分配新对象的需要,就会出现一次“并发失败”(Concurrent Mode Failure),这时候虚拟机将不 得不启动后备预案:冻结用户线程的执行,临时启用Serial Old收集器来重新进行老年代的垃圾收集, 但这样停顿时间就很长了。

3.还有最后⼀个缺点,CMS是⼀款基于“标记-清除”算法实现的收集器,这意味着收集结束时会有⼤量空间碎⽚产⽣。空间碎⽚过多时,将会给⼤对象分配带来很⼤麻烦,往往会出

现⽼年代还有很多剩余空间,但就是⽆法找到⾜够⼤的连续空间来分配当前对象,⽽不得

不提前触发⼀次Full GC的情况。 因此虚拟机设计者们还提供了另外⼀个参数-XX: CM

SFullGCsBefore- Compaction(此参数从JDK 9开始废弃),这个参数的作⽤是要求CMS收

集器在执⾏过若⼲次(数量由参数值决定)不整理空间的Full GC之后,下⼀次进⼊Full GC

前会先进⾏碎⽚整理(默认值为0,表示每次进⼊Full GC时都进⾏碎⽚整理)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值