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


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

文章插图
【这应该是全网最全的CMS学习笔记了-cms教程大全】可中断预清理由于时光退出
有可能可中断预清理过程中一直没等到Minor gc 。这时候进入从头开始标记阶段的话 。新生代还有非常多活着的对象 。就回导致STW变长 。因此CMS还提供了CMSScavengeBeforeRemark参数 。可以在进入从头开始标记以前强烈进行依次Minor gc 。
(STW)从头开始标记:从头开始扫描堆中的对象 。进行可达性解析,标记活着的对象 。这种阶段扫描的目标是:新生代的对象 + Gc Roots + 前面被标记为dirty的card对应的老时代对象 。如果预清理的事情没做好 。这一步扫描新生代的时候就会花非常多的时间 。导致这种阶段的停顿时光过长 。这种过程是多线程的 。并发清除:玩家线程被从头开始激活 。同一时间将那些未被标记为存活的对象标记为不可达;并发重置:CMS内部重置回收器情况 。准备进入下一个并发回收周期 。CMS的不正常状态上面描述的是CMS的并发周期正常完成的状态 。但是还有几种CMS并发周期失败的状态:
并发模式失败(Concurrent mode failure):CMS的目标就是在回收老时代对象的时候不要终止全部应用线程 。在并发周期执行期间 。玩家的线程依然在运行 。如果这时候如果应用线程向老时代请求分配的空间超过预留的空间(担保失败) 。就回触发concurrent mode failure 。之后跟着CMS的并发周期就会被一次Full GC代替——终止全部应用进行垃圾获得 。并进行空间压缩 。如果我们设置了UseCMSInitiatingOccupancyOnly和CMSInitiatingOccupancyFraction参数 。之中CMSInitiatingOccupancyFraction的值是70 。那预留空间就是老时代的30% 。晋升失败:新生代做minor gc的时候 。需要CMS的担保机制确认老时代是否有足够的空间容纳要晋升的对象 。担保机制发现不够 。则报concurrent mode failure 。如果担保机制判断是够的 。但是事实上由于碎片问题导致无法分配 。就会报晋升失败 。永久代空间(或Java8的元空间)耗尽 。默认状态下,CMS不会对永久代进行获得 。只要永久代空间耗尽 。就回触发Full GC 。三、CMS的调优针对停顿时光过长的调优 首先需要判断是哪个阶段的停顿导致的 。之后跟着再针对详细的原因进行调优 。使用CMS获得器的JVM可能引发停顿的状态有:(1)Minor gc的停顿;(2)并发周期里初始标记的停顿;(3)并发周期里从头开始标记的停顿;(4)Serial-Old获得老时代的停顿;(5)Full GC的停顿 。之中并发模式失败会导致第(4)种状态 。晋升失败和永久代空间耗尽会导致第(5)种状态 。针对并发模式失败的调优想到一个办法增大老时代的空间 。增加整个堆的大小 。或者减少年轻代的大小以更高的频率执行后台的回收线程 。即提升CMS并发周期发生的频率 。设置UseCMSInitiatingOccupancyOnly和CMSInitiatingOccupancyFraction参数 。调低CMSInitiatingOccupancyFraction的值 。但是也不可以调得太低 。太低了会导致过多的无效的并发周期 。会导致消耗CPU时光和再多的无效的停顿 。一般来讲 。这种过程需要几个迭代 。但是还是有一定的套路 。参见《Java性能权威指南》中给出的反馈 。摘抄如下:对特殊的应用软件程序 。该标志的更优值可以根据 GC 日志中 CMS 周期首次启动失败时的值获得 。详细途径是 。在垃圾回收日志中找到并发模式失效 。寻找后再反向查找 CMS 周期最近的启动记录 。之后跟着根据日志来计算这时候的老时代空间占用值 。之后跟着设置一个比该值更小的值 。增多回收线程的个数 CMS默认的垃圾获得线程数是(CPU个数 + 3)/4 。这种公式的含义是:当CPU个数大于4个的时候 。垃圾回收后台线程至少占用25%的CPU资源 。举个举例:如果CPU核数是1-4个 。那么会有1个CPU用来垃圾获得 。如果CPU核数是5-8个 。那么久会有2个CPU用来垃圾获得 。
针对永久代的调优
如果永久代需要垃圾回收(或元空间扩容) 。就会触发Full GC 。默认状态下 。CMS不会处理永久代中的垃圾 。可以通过开启CMSPermGenSweepingEnabled配置来开启永久代中的垃圾回收 。开启后会有一组后台线程针对永久代做获得 。需要小心的是 。触发永久代进行垃圾获得的指标跟触发老时代进行垃圾获得的指标是独立的 。老时代的阈值可以通过CMSInitiatingPermOccupancyFraction参数设置 。这种参数的默认值是80% 。开启对永久代的垃圾获得只是之中的一步 。还需要开启另外一个参数——CMSClassUnloadingEnabled 。使得在垃圾获得的时候可以卸载不用的类 。

推荐阅读