CMS垃圾收集器收集详细步骤算法
标记GcRoots直接可达老年对象,新生代存活对象引用的老年代对象.整个过程在JDK1.7中是单线程的在JDK1.8中是多线程的(经过CMSParallelInitialMarkEnabled参数调整)。这个过程会致使STW。
从
初始标记
阶段标记过的对象开始,标记其它存活对象,这个阶段垃圾回收线程和应用线程同时运行。因为是同时运行,应用线程还在跑,会致使对象的晋升,对象引用的变化,特殊对象直接分配到老年代。这些受到影响的老年代对象所在的Card会被标记成Dirty,用于从新标记阶段扫描,老年代对象的Card被标记为Dirty的可能缘由以下面绿线所示。
因为上一个阶段是并发执行的未标记的变化对象只是标记成了Dirty对象,尚未处理,预清理
就是来标记这些Dirty对象
。以下图:在并发标记阶段3号Card被标志为Dirty。这个阶段是为从新标记
阶段作准备。
预清理将6号标志为存活对象多线程
这个阶段也是为从新标志阶段作准备,在进入从新标志阶段前,最好能进行一个Minor GC,将年轻代清理一遍, 这样能够清除大部分年轻代的对象(绝大部分年轻代对象朝生夕死),尽可能缩短
从新标记
阶段停顿时间,CMS还提供了CMSScavengeBeforeRemark参数,能够在进入从新标记以前强制进行依次Minor gc。
预清理
和可被终止的预清理
都是为从新标志
阶段作准备,因为从新标志
阶段会发生(STW),因此要保证尽肯能的停顿时间段,否则就会影响应用程序的用户体验。这个阶段扫描的目标是:年轻代+GC Roots+Dirty老年代对象,这个阶段是多线程的(XX:+CMSParallelRemarkEnabled)。
用户线程被激活,那些未被标志的对象会被清除。'
CMS垃圾收集器参数回到初始状态,为下一次垃圾收集作准备。
从新标记
停顿时间过长80%的时间花在从新标志
阶段,若是发现从新标志
阶段停顿时间过长,可尝试添加-XX:+CMSScavengeBeforeRemark
,在从新标志
以前作一次Minor GC
,目的是减小对老年代对象的无效引用,下降从新标志
的开销。
CMS是基于标记-清除算法的,CMS只会删除垃圾对象,不会对内存空间作压缩,会形成内存碎片。咱们须要用-XX:CMSFullGCsBeforeCompaction=n
参数来调整,含义是在上一次CMS并发执行事后,还要执行多少次Full GC
才作内存压缩.
在CMS GC过程当中因为应用程序也在跑,当年轻代满了,执行了
Minor GC
这时候,须要将存活对象放入老年代,而此时老年代空间也不足,这时CMS尚未机会回收老年代。能够设置如下两个参数
CMS对内存的占用率达到75%将启动GC,默认为92%,过高将致使
promotion failed
若是没有设置UseCMSInitiatingOccupancyOnly
,只设置了CMSInitiatingOccupancyFraction
那么JVM只在第一次使用,后续会进行自动调整。为何要设置以上两个参数,在垃圾收集阶段,用户线程还在运行,因此必需要留够空间让用户线程运行。CMS前五个阶段都是标记存活对象的,除了”初始标记”和”从新标记”阶段会stop the word ,其它三个阶段都是与用户线程一块儿跑的,就会出现这样的状况gc线程正在标记存活对象,用户线程同时向老年代提高新的对象,清理工做尚未开始,old gen已经没有空间容纳更多对象了,这时候就会致使concurrent mode failure, 而后就会使用串行收集器回收老年代的垃圾,致使停顿的时间很是长。
CMSInitiatingOccupancyFraction参数要设置一个合理的值,设置大了,会增长concurrent mode failure发生的频率,设置的小了,又会增长CMS频率,因此要根据应用的运行状况来选取一个合理的值。若是发现这两个参数设置大了会致使full gc,设置小了会致使频繁的CMS GC,说明你的老年代空间太小,应该增长老年代空间的大小了。并发
在进行Minor GC时,Survivor space放不下,对象只能放入老年代,而此时老年代也放不下,大多数状况是老年代内存碎片太多,致使没有连续的空间存放对象。
发生Minor GC时,若是对象过大(Survivor Space存放不下)基本上会放到老年代,这种现象被称为对象过早晋升,这将致使老年代被中短时间对象增张,肯能致使严重的性能问题。若是老年代也满了,会触发Full GC,这将会致使遍历整个堆,晋升失败。
-XX:CMSFullGCsBeforeCompaction=n
,有规律对内存进行整理减小内存碎片。XX:+UseConcMarkSweepGC
-XX:CMSFullGCsBeforeCompaction=n
Full GC
n 次后进行内存压缩整理-XX:CMSInitiatingOccupancyFraction=70
-XX:+UseCMSInitiatingOccupancyOnly
内存占用70%将触发CMS GC
-XX:+CMSScavengeBeforeRemark
CMS GC前执行一次Minor GC