cms垃圾回收器

cms参数:

UseConcMarkSweepGC:使用cms垃圾回收器
CMSFullGCsBeforeCompaction:几次full gc整理压缩一次 默认0
UseCMSInitiatingOccupancyOnly:假设没有这个参数,只有第一次发生cms gc的时候会使用CMSInitiatingOccupancyFraction参数值 后面jvm会动态调整
CMSInitiatingOccupancyFraction:指CMS在对内存占用率达到一定的时候开始GC 默认92%
CMSScavengeBeforeRemark:在CMS GC前启动一次ygc,目的在于减少old gen对ygc gen的引用,降低remark时的开销(一般CMS的GC耗时 80%都在remark阶段)
    CMSScheduleRemarkEdenSizeThreshold、CMSScheduleRemarkEdenPenetration,默认值分别是2M、50%。两个参数组合起来的意思是预清理后,eden空间使用超过2M时启动可中断的并发预清理,直到eden空间使用率达到50%时中断,进入重新标记阶段。

cms gc触发时机:
阈值检查机制:老年代的使用空间达到某个阈值,JVM的默认值是92%(jdk1.5之前是68%,jdk1.6之后是92%),或者可以通过CMSInitiatingOccupancyFraction和UseCMSInitiatingOccupancyOnly两个参数来设置;这个参数的设置需要看应用场景,设置得太小,会导致CMS频繁发生,设置得太大,会导致过多的并发模式失败。例如

动态检查机制:JVM会根据最近的回收历史,估算下一次老年代被耗尽的时间,快到这个时间的时候就启动一个并发周期。设置UseCMSInitiatingOccupancyOnly这个参数可以将这个特性关闭。

full gc触发的时机:

1:System.gc()。如果没有开启禁止调用system.gc() DisableExplicitGC;
2:promotion failed:这种情况通常是对象要晋升到老年代中时,发现老年代的内存不足了,所以要引发一次Full GC。对象的晋升分为正常晋升(活过15代)和提前晋升(大对象、survival区装不下)。
3:concurrent mode failure:在执行CMS GC的过程中同时有对象要放入老年代,而此时老年代空间不足造成的
4:metaSpace空间不够
5:jmap -dump:live触发

CMS退化为serial gc的情况:

 promotion failed 不会 导致fullGC中的CMS退化为serialGC
 concurrent mode failure会引起Full GC,这种情况下会使用Serial Old收集器,是单线程的,对GC的影响很大。

CMS GC 过程:CMS GC仅仅是堆old区进行回收。

1:初始标记 :在这个阶段,需要STW。这个过程从root set开始,只扫描到能够和root set直接关联的对象,并作标记。jdk1.8后这一步是并发的。这里的root set不包含年轻代。

2:并发标记 :这个阶段紧随初始标记阶段,在初始标记的基础上继续向下追溯标记。并发标记阶段,应用程序的线程和并发标记的线程并发执行,所以用户不会感受到停顿。

3:预清理阶段:这个阶段会处理在并发标记过程中eden区发生变化的引用(特指eden指向old gen的引用变化),此外还会处理dirty card中的引用。

4:可中断预清理阶段:这个阶段主要处理from和to区域对象引用old gen的变化,同样也会继续处理dirty card的对象引用。触发的条件:Eden的占用量>CMSScheduleRemarkEdenSizeThreshold(默认为2M),中断的条件:Eden区占用量>CMSScheduleRemarkEdenPenetration(默认50%),或达到5秒钟。

5:重新标记 :STW 扫一遍root set,root set包含年轻代。CMS的remark需要重新扫描mod-union table里的dirty card外加整个根集合,而此时整个young gen(不管对象死活)都会被当作根集合的一部分,因而CMS remark有可能会非常慢。

6:并发清理 :清理垃圾对象,这个阶段收集器线程和应用程序线程并发执行。

7:并发重置 :这个阶段,重置CMS收集器的数据结构,等待下一次垃圾回收。

CMS的Precleaning(预清理)和AbortablePreclean(可中断的预清理)

预清理和可中断预清理这两个阶段并不是必须的,可以通过参数XX:-CMSPrecleaningEnabled关闭。

Free list space:cms gc回收会产生不连续的内存,用一个链表把他们连起来,当用户请求分配时,系统从可利用空间表中删除一个结点分配之;当用户释放其所占内存时,系统即回收并将它插入到可利用空间表中。

三色标记法:
黑色:从GCRoots开始,已扫描过它全部引用的对象,标记为黑色
灰色:扫描过对象本身,还没完全扫描过它全部引用的对象,标记为灰色
白色:还没扫描过的对象,标记为白色

三色标记的漏标问题产生的原因:漏标会导致理应活着的对象被回收

有至少一个黑色对象在自己被标记之后指向了这个白色对象
所有的灰色对象在自己引用扫描完成之前删除了对白色对象的引用

CMS的处理 INC barrier:

如果一个黑色对象添加了一个白色对象,就把这个黑色对象变灰。这样重新标记的时候就会继续扫描他。这个存有一项缺陷:无法发现 Concurrent Mark 期间堆外根集(寄存器、栈)的引用变化。为此在 concurrent mark 之后,需要一个 remark 阶段再 STW 扫一遍root set。

你可能感兴趣的:(java)