CMS
简介
cms全称 Concurrent Mark Sweep,是一款并发的、使用标记-清除算法的垃圾回收器,再jdk1.5中开始使用。
cms设计的目标:是为了达到 最低停顿时间(stop the world停顿时间)
使用场景:GC过程短暂,适合对时延要求较高的服务,对服务器响应要求较高的服务
特点
1、并发
2、基于标记-清除
算法实现
3、是一个老年代垃圾收集器,可以和Serial、Parallel New收集器配合使用。当并行模式(concurent mode failure)失败时CMS会退化成Serial Old.
CMS收集器工作流程
- 初始标记(Initial Mark):只标记和GC Root能直连的对象(可达对象),速度快,会发生"stop the world"。
- 并发标记(Concurrent Mark):和应用线程并发执行,遍历“初始标记”阶段标记过的对象,标记这些对象的可达对象。
- 重新标记(Final Remark):由于“并发标记”和应用线程是并发执行的,所以有些标记的对象会发生了变化。“重新标记”比“初始标记”时间长,比“并发标记”时间短。会发生"stop the world"。
- 并发清理(Concurrent Sweep):和应用线程一起运行。基于标记对象,直接清理对象,回收被占用的空间。
- 并发重置(Concurrent Reset):并发重置阶段,将清理并恢复在CMS GC过程中的各种状态,重新初始化CMS相关数据结构,为下一个垃圾收集周期做好准备。
常见问题补充
为什么配置了CMS GC,却触发了Full GC?
(1)大对象分配时,年轻代放不下,直接去了老年代,结果老年代也放不下,直接触发Full GC。
(2)使用标记-清除
算法存在 内存碎片 问题。
(3)CMS GC失败(Concurrent mode failure导致)
(4)jmap -histo人为执行了命令
CMS收集器存在的问题
- 消耗CPU资源
由于CMS是并发设计的,并发程序都对CPU资源比较敏感。CMS默认启动的回收线程是(cpu数量+3)/4,CMS工作时占用一部分线程,导致系统总吞吐量会降低。所以系统需要提高CPU资源来提高服务的吞吐量。 - 内存碎片问题
由于CMS采用的是标记-清除
算法,所以内存碎片问题是不可避免的。
解决办法:使用-XX:+CMSFullGCsBeforeCompaction=n
,意思是在上次CMS并发GC执行过后,还需要做多少次Full GC才做压缩。默认是0,也就是说只要发生Full GC时就压缩整理。 - 无法处理浮动垃圾
- CMS并发清理阶段,用户程序还在执行,会需要预留一部分空间。CMS的做法是是用-XX:CMSInitiatingOccupancyFraction=60参数控制老年代空间占用率达到某个阈值时触发垃圾回收。
- 如果预留的空间不够使用,就会出现
Concurrent Mode Failure
,此时会触发一次Full GC,转而使用Serial Old收集器对老年代进行垃圾回收,会产生stop the world,耗时较长。Concurrent Mode Failure一般会伴随ParNew promotion failed,晋升担保失败,就是为了应对新生代GC后产生存活对象过多,Survivor区无法容纳的情况,需要老年代有足够的空间容纳这些对象,如果老年代没有足够的空间,就会产生担保失败。 - 如何避免Concurrent Mode Failure
(1)调大老年代的空间
(2)调低CMSInitiatingOccupancyFraction配置的值,使能够及时回收空间,但是也会造成频繁CMS GC
(3)代码层面优化,控制对象创建频率
- 重新标记阶段时间过长
解决:使用 -XX:+CMSScavengeBeforeRemark,在执行重新标记前先做一次Young GC,目的在于。。。
生产参数配置案例
jvmparams=-Dcom.sun.management.jmxremote.ssl\=false -Dcom.sun.management.jmxremote.authenticate\=false -Xms2000m -Xmx2000m -Xmn1000m -Xss1000k
-XX:PermSize\=512M
-XX:+UseConcMarkSweepGC
-XX:CMSInitiatingOccupancyFraction\=60
-XX:+PrintGCApplicationStoppedTime
-XX:+PrintGCDateStamps
-XX:+CMSParallelRemarkEnabled
-XX:+CMSScavengeBeforeRemark
-XX:+UseCMSCompactAtFullCollection
-XX:CMSFullGCsBeforeCompaction\=0 -verbosegc
-XX:+PrintGCDetails
-XX:ErrorFile\=/usr/local/app/taf/app_log/