这应该是全网最全的CMS学习笔记了-cms教程大全( 三 )


四、CMS的trade-off是什么?优势
低延迟的获得器:几乎没有很长时间的停顿 。应用软件程序只在Minor gc以及后台线程扫描老时代的时候发生极其短暂的停顿 。劣势
更高的CPU使用:一定有足够的CPU资源用来运行后台的垃圾获得线程 。在应用软件程序线程运行的同一时间扫描堆的使用状态 。【PS:现在服务器的CPU资源基础不是问题 。这种点可以忽略】CMS获得器对老时代获得的时候 。不再进行所有压缩和整理的事情 。说明着老时代随着应用的运行会变得碎片化;碎片过多会波及大对象的分配 。即便老时代还有蛮大的剩余空间 。但是没有连续的空间来分配大对象 。这时候就会触发Full GC 。CMS提供了两个参数来解决这种问题:(1)UseCMSCompactAtFullCollection 。在要进行Full GC的时候进行内存碎片整理;(2)CMSFullGCsBeforeCompaction 。每隔多少次不压缩的Full GC后 。执行一次带压缩的Full GC 。会出现浮动垃圾;在并发清理阶段 。玩家线程依然在运行 。一定预留出空间给玩家线程使用 。因此CMS比很多回收器需要更大的堆空间 。五、几个问题的解答为什么ParNew可以和CMS搭配使用 。而Parallel Scanvenge不可以?
答:这种跟Hotspot VM的简史有关 。Parallel Scanvenge是不在“分代框架”下研究的 。而ParNew、CMS都是在分代框架下研究的 。
CMS中minor gc和major gc是顺序发生的吗?
答:不是的 。可以交叉发生 。即在并发周期执行过程中 。是可以发生Minor gc的 。这种找个gc日志就可以研究到 。
CMS的并发获得周期适合触发?
由下图可以就这样看出 。CMS 并发周期触发的条件有两个:

这应该是全网最全的CMS学习笔记了-cms教程大全

文章插图
触发cms并发周期的条件
阈值检查机制:老时代的使用空间达到某个阈值 。JVM的默认值是92%(jdk1.5以前是68% 。jdk1.6之后是92%) 。或者可以通过CMSInitiatingOccupancyFraction和UseCMSInitiatingOccupancyOnly两个参数来设置;这种参数的设置需要就这样看应用场景 。设置得太小 。会导致CMS频繁发生 。设置得太大 。会导致过多的并发模式失败 。比如
动态检查机制:JVM会根据最近的回收简史 。估算下一次老时代被耗尽的时光 。快到这种时光的时候就启动一个并发周期 。设置UseCMSInitiatingOccupancyOnly这种参数可以将这种特性关闭 。
CMS的并发获得周期会扫描哪些对象?会回收哪些对象?
答:CMS的并发周期只会回收老时代的对象 。但是在标记老时代的存活对象时 。可能有的对象会被年轻代的对象引用 。因此需要扫描整个堆的对象 。
CMS的gc roots包括哪些对象?
答:首先 。在JVM垃圾获得中Gc Roots的概念怎么样理解(参见R大对GC roots的概念的解答);第二 。CMS的并发获得周期中 。怎么样判断老时代的对象是活着?我们前面提到了 。在CMS的并发周期中 。仅仅扫描Gc Roots直达的对象会有遗漏 。还需要扫描新生代的对象 。如下图中的蓝色字体所示 。CMS中的年轻代和老时代是分别获得的 。因此在判断年轻代的对象存活的时候 。需要把老时代当作自己的GcRoots 。这时候并不需要扫描老时代的全部对象 。而是使用了card table资料结构 。如果一个老时代对象引用了年轻代的对象 。则card中的值会被设置为特定的数值;反过来判断老时代对象存活的时候 。也需要把年轻代当作自己的Gc Roots 。这种过程我们在第三节已经论述过了 。
这应该是全网最全的CMS学习笔记了-cms教程大全

文章插图
老时代和新生代互相作为Gc Roots
如果我的应用决定使用CMS获得器 。介绍的JVM参数是什么?我自己的应用使用的参数如下 。是根据PerfMa的xxfox生成的 。各位也完全可以使用这种业务调优自己的JVM参数:
这应该是全网最全的CMS学习笔记了-cms教程大全

文章插图
CMS有关的参数总结(需要小心的是 。这里我没有思考太多JDK版本的问题 。JDK1.7和JDK1.8这些参数的配置 。有的默认值可能不一样 。详细使用的时候还需要根据详细的版本来确认怎么去调配设置)
这应该是全网最全的CMS学习笔记了-cms教程大全

文章插图

推荐阅读