谈谈对CMS的认知?

CMS(concurrent mark sweep)在jdk1.5中曾经开始应用了,2004年9月30日,JDK1.5公布。CMS设计的指标就是获取最低进展工夫(stop the world进展工夫),它是基于标记-革除算法实现的。罕用的场景是互联网网站(对服务响应要求较高),它是一个老年代垃圾收集器,能够和Serial收集器,Parallel New收集器配合应用。当并行模式(concurrent mode failure)失败时CMS会进化成Serial Old.

CMS收集器的工作流程(步骤)是什么样的?

次要四个阶段
  • 初始标记:只标记和GC Roots能直连的对象,速度快,会产生(stop the world)
  • 并发标记:和利用线程并发执行,遍历初始标记阶段标记过的对象,标记这些对象的可达对象。
  • 从新标记:因为并发标记是和利用线程是并发执行的,所以有些标记过的对象产生了变动。这个过程比初始标记用时长,然而比并发标记阶段用时短。会产生(stop the world)
  • 并发革除:和利用线程一起运行。基于标记对象,间接清理对象。

CMS的毛病?

垃圾碎片问题

  • 起因:因为CMS采纳的是标记-革除算法,所以不可避免会有内存碎片问题。
  • 解决:应用-XX:+CMSFullGCsBeforeCompaction=n,意思是在上次CMS并发GC执行过后,到底还要做多少Full GC才做压缩。默认是0,也就是说每次CMS GC顶不住了转入Full GC时都要压缩。

并发模式失败(concurrent mode failure)

  • 起因:CMS垃圾清理线程和利用线程是并发执行的,如果在清理过程中老年代空间有余不能包容新对象。
  • 解决:应用-XX:+UseCMSInitiatingOccupancyOnly-XX:CMSInitiatingOccupancyFraction=60,指定CMS对内存的占用率到60%时开始GC。

从新标记阶段工夫过长

  • 解决:应用-XX:+CMSScavengeBeforeRemark,在执行从新标记之前,先做一次Young GC,目标在于较少年老代对老年代的有效援用,升高从新标记的开销。

为什么配置了CMS GC,却触发了Full GC?

  • 大对象调配时,年老代放不下,间接去老年代,后果老年代也放不下。
  • 内存碎片问题(应用标记-革除算法的毛病)
  • CMS GC失败(concurrent mode failure导致)
  • jmap -histo 人为执行了命令