CMS并行GC收集器是大多数JAVA服务应用的最佳选择,然而, CMS并不是完美的,在使用CMS的过程中会产生2个最让人头痛的问题:

promotion failed

该问题是在进行Minor GC时,Survivor Space放不下,对象只能放入老年代,而此时老年代也放不下造成的。(promotion failed时老年代CMS还没有机会进行回收,又放不下转移到老年代的对象,因此会出现下一个问题concurrent mode failure,需要stop-the-wold 降级为GC-Serail Old)。
下面是一个promotion failed的一条gc日志:

106.641: [GC 106.641: [ParNew (promotion failed): 14784K->14784K(14784K), 0.0370328 secs]106.678: [CMS106.715: [CMS-concurrent-mark: 0.065/0.103 secs] [Times: user=0.17 sys=0.00, real=0.11 secs]
(concurrent mode failure): 41568K->27787K(49152K), 0.2128504 secs] 52402K->27787K(63936K), [CMS Perm : 2086K->2086K(12288K)], 0.2499776 secs] [Times: user=0.28 sys=0.00, real=0.25 secs]

concurrent mode failure

该问题是在执行CMS GC的过程中同时业务线程将对象放入老年代,而此时老年代空间不足,或者在做Minor GC的时候,新生代Survivor空间放不下,需要放入老年代,而老年代也放不下而产生的。
下面是一个concurrent mode failure的一条gc日志:

0.195: [GC 0.195: [ParNew: 2986K->2986K(8128K), 0.0000083 secs]0.195: [CMS0.212: [CMS-concurrent-preclean: 0.011/0.031 secs] [Times: user=0.03 sys=0.02, real=0.03 secs]
(concurrent mode failure): 56046K->138K(57344K), 0.0271519 secs] 59032K->138K(65472K), [CMS Perm : 2079K->2078K(12288K)], 0.0273119 secs] [Times: user=0.03 sys=0.00, real=0.03 secs]

下面我们详细的分析这两个问题产生的原因以及如何进行解决。

首先我们经常遇到promotion failed问题,这也确实是个很头痛的问题,一般是进行Minor GC的时候,发现Survivor空间不够,所以,需要移动一些新生带的对象到老年带,然而,有些时候尽管老年代有足够的空间,但是由于CMS采用标记清除算法,默认并不使用标记整理算法,可能会产生很多碎片,因此,这些碎片无法完成大对象向老年带转移,因此需要进行CMS在老年带的Full GC来合并碎片。

这个问题的直接影响就是它会导致提前进行CMS Full GC, 尽管这个时候CMS的老年代并没有填满,只不过有过多的碎片而已,但是Full GC导致的stop-the-wold是难以接受的。

解决这个问题的办法就是可以让CMS在进行一定次数的Full GC(标记清除)的时候进行一次标记整理算法,CMS提供了以下参数来控制:

-XX:UseCMSCompactAtFullCollection -XX:CMSFullGCBeforeCompaction=5
也就是CMS在进行5次Full GC(标记清除)之后进行一次标记整理算法,从而可以控制老年代的碎片在一定的数量以内,甚至可以配置CMS在每次Full GC的时候都进行内存的整理。

另外,有些应用存在比较大的对象朝生熄灭,这些对象在救助空间无法容纳,因此,会提早进入老年代,老年代如果有碎片,也会产生promotion failed, 因此我们应该控制这样的对象在新生代,然后在下次Minor GC的时候就被回收掉,这样避免了过早的进行CMS Full GC操作,下面的一个配置样例就通过增加Survivor空间的大小来解决这个问题:

-Xmx4000M -Xms4000M -Xmn600M -XXmSize=500M -XX:MaxPermSize=500M -Xss256K -XX:+DisableExplicitGC -XX:SurvivorRatio=1 -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+CMSParallelRemarkEnabled eCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=0 -XX:+CMSClassUnloadingEnabled -XX:LargePageSizeInBytes=128M -XX:+UseFastAccessorMethods -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=80 -XX:SoftRefLRUPolicyMSPerMB=0 -XX:+PrintClassHistogram -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintHeapAtGC -Xloggc:log/gc.log

上面讨论了promotion failed引起的原因以及解决方案,除了promotion failed还有一个情况会引起CMS回收失败,从而退回到Serial Old收集器进行回收,我们在线上尤其要注意的是concurrent mode failure出现的频率,这可以通过-XX:+PrintGCDetails来观察,当出现concurrent mode failure的现象时,就意味着此时JVM将继续采用Stop-The-World的方式来进行Full GC,这种情况下,CMS就没什么意义了,造成concurrent mode failure的原因是当minor GC进行时,1)旧生代所剩下的空间小于Eden区域+From区域的空间,或者2)在CMS执行老年代的回收时有业务线程试图将大的对象放入老年代,导致CMS在老年代的回收慢于业务对象对老年代内存的分配。

解决这个问题的通用方法是调低触发CMS GC执行的阀值,CMS GC触发主要由CMSInitiatingOccupancyFraction值决定,默认情况是当旧生代已用空间为68%时,即触发CMS GC,在出现concurrent mode failure的情况下,可考虑调小这个值,提前CMS GC的触发,以保证旧生代有足够的空间。

总结:

  1. promotion failed – concurrent mode failure
    Minor GC后, Survivor空间容纳不了剩余对象,将要放入老年代,老年代有碎片或者不能容纳这些对象,就产生了concurrent mode failure, 然后进行stop-the-world的Serial Old收集器。

解决办法:-XX:UseCMSCompactAtFullCollection -XX:CMSFullGCBeforeCompaction=5 或者调大新生代或者Survivor空间

  1. concurrent mode failure

CMS是和业务线程并发运行的,在执行CMS的过程中有业务对象需要在老年代直接分配,例如大对象,但是老年代没有足够的空间来分配,所以导致concurrent mode failure, 然后需要进行stop-the-world的Serial Old收集器。

解决办法:+XX:CMSInitiatingOccupancyFraction,调大老年带的空间,+XX:CMSMaxAbortablePrecleanTime

总结一句话:使用标记整理清除碎片和提早进行CMS操作。

【转自】https://my.oschina.net/hosee/blog/674181

CMS之promotion failedconcurrent mode failure相关推荐

  1. CMS垃圾收集器详解

    概述 CMS垃圾收集器是一款优秀的老年代并发垃圾收集器,通过与用户线程并发执行的方式减少GC停顿的时间.本文主要聊一下CMS设计到的相关的数据结构.具体的执行过程.运行中会出现的异常情况. 在CMS之 ...

  2. 总结CMS常见面试题

    谈谈对CMS的认知? CMS(concurrent mark sweep)在jdk1.5中已经开始使用了,2004年9月30日,JDK1.5发布.CMS设计的目标就是获取最低停顿时间(stop the ...

  3. 0 full gc时cpu idle_结合GC日志讲讲CMS垃圾收集器

    1 CMS垃圾收集器介绍 CMS(Concurrent Mark Sweep)收集器旨在获取最短回收停顿时间的并发垃圾收集器.CMS基于"标记-清除"算法实现,并发指的是CMS的垃 ...

  4. CME CMS ERROR错误代码

    Error Description 4G通信模块指令错误码描述 CME ERROR's (GSM Equipment related codes) CME ERROR: 0 Phone failure ...

  5. 在linux上gc日志详解,JVM CMS GC日志详解

    # JDK8 -Xms20M -Xmx20M -XX:+PrintGCDetails -XX:+UseConcMarkSweepGC CMS 日志格式: [GC (Allocation Failure ...

  6. 炸了!一口气问了我18个JVM问题!

    young gc.old gc.full gc.mixed gc 傻傻分不清? 这个问题的前置条件是你得知道 GC 分代,为什么分代.这个在之前文章提了,不清楚的可以去看看. 现在我们来回答一下这个问 ...

  7. 面试官不讲武德,竟然问了我18个JVM问题!

    前言 GC 对于Java 来说重要性不言而喻,不论是平日里对 JVM 的调优还是面试中的无情轰炸. 这篇文章我会以一问一答的方式来展开有关 GC 的内容. 本文章所说的 GC 实现没有特殊说明的话,默 ...

  8. JVM面试题(含答案和图和解释)

    整理不易,如果对你有帮助,请点赞收藏+关注,请仔细阅读,个别问题涉及到的知识点比较多,看似只有[121],但是扩展的问题还是很多的,所以料很足,请耐心观阅,面试题包含了[类加载机制][运行时数据区][ ...

  9. 学习笔记【Java 虚拟机②】垃圾回收

    若文章内容或图片失效,请留言反馈.部分素材来自网络,若不小心影响到您的利益,请联系博主删除. 总目录 学习笔记[Java 虚拟机①]内存结构 学习笔记[Java 虚拟机②]垃圾回收 学习笔记[Java ...

最新文章

  1. android tombstone发生过程,Android Tombstone 分析
  2. 北京发自动驾驶车辆考试大纲 难度堪比普通人考驾照
  3. collection_check_boxes的应用
  4. tRNAscan-SE 预测tRNA基因
  5. UITableView样式和UITableViewCell样式
  6. crash工具解析_Linux 后台开发常用调试工具
  7. 英语发音规则---发/i:/的字母及字母组合
  8. 九、Spark模块和安装
  9. 数仓dw怎么建_搭建数据仓库的流程简介
  10. Android之如何ubuntu环境下在手机里面快速找到apk的位置然后拉下来
  11. 于.net开发平台项目案例集锦
  12. HBase-scan简介及优化(缓存与批量处理)
  13. VS Code 取色器 插件 颜色选取
  14. 用注册表修改右键菜单
  15. Java中Math类的随机数公式
  16. C语言数据结构之一元多项式的求导
  17. C#强密匙加密文件.snk
  18. Android旅游自助项目之订票系统订票功能实现
  19. android 电容屏多点触控协议
  20. 如何将PDF转换Word?微信如何转换PDF文件?

热门文章

  1. vba移动文件_Excel VBA之FSO-2.3文件夹的移动
  2. linux终端命令教程,Linux终端命令入坑技巧
  3. 传统公司部署OpenStack(t版)简易介绍(九)——控制台部署
  4. 电脑无法连接到系统服务器,请问怎么客户端的电脑连接不到服务器?这是什么原因?...
  5. C语言面试题分享(3)
  6. GPT转MBR怎么转?GPT转MBR完整图文教程
  7. html效果属性是,htmltransition属性
  8. python缩进格式作用_关于自动缩进格式问题,高手帮忙!
  9. js打印线程id_一文讲透“进程,线程和协程”
  10. el-table 行背景颜色_用手机拍花卉怎样使背景变黑?