转载于:面试官100%会严刑拷打的 CMS 垃圾回收器
cms工作流程:
- 初始标记:仅仅只是标记一下GC Roots能直接关联到的对象,速度很快,需要“Stop The World”。
- 并发标记:进行GC Roots Tracing的过程,在整个过程中耗时最长。
- 重新标记:为了修正并发标记期间因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间一般会比初始标记阶段稍长一些,但远比并发标记的时间短。此阶段也需要“Stop The World”。
- 并发清除。
cms缺陷:
1、垃圾碎片的问题,我们都知道CMS是使用的是标记-清除算法的,所以不可避免的就是会出现垃圾碎片的问题。
2、一般CMS的GC耗时80%都在remark阶段,remark阶段停顿时间会很长,在CMS的这四个主要的阶段中,最费时间的就是重新标记阶段。
3、concurrent mode failure,由于并发清除阶段是和用户线程同时运行的,用户线程的运行占用了过多内存,造成老年代空间不足的情况。
4、promotion failure,这个问题是指,在进行Minor GC时,Survivor空间不足,对象只能放入老年代,而此时老年代也放不下造成的,多数是由于老年代有足够的空闲空间,但是由于碎片较多,新生代要转移到老年带的对象比较大,找不到一段连续区域存放这个对象导致的。
解决方案:
1、垃圾碎片的问题:针对这个问题,这时候我们需要用到这个参数:-XX:CMSFullGCsBeforeCompaction=n
意思是说在上一次CMS并发GC执行过后,到底还要再执行多少次full GC才会做压缩。默认是0,也就是在默认配置下每次CMS GC顶不住了而要转入full GC的时候都会做压缩。
2、concurrent mode failure,设置参数
-XX:CMSInitiatingOccupancyFraction=60
,它是指设定CMS在对内存占用率达到60%的时候开始GC。
3、remark阶段停顿时间会很长的问题:设置参数,-XX:+CMSScavengeBeforeRemark
。在执行remark操作之前先做一次Young GC,目的在于减少年轻代对老年代的无效引用,降低remark时的开销。