采访者:今天聊聊CMS垃圾收集器吧?考生:嗯……考生:如果你使用Seria和Parallel系列的垃圾收集器:在垃圾收集过程中,用户线程会完全停止,直到垃圾收集结束!候选:CMS全称:ConcurrentMarkSweep,译为“ConcurrentMarkSweep”线程在工作时,用户线程“不会完全停止”,用户线程在“某些场景”下与GC线程并发执行.候选人:但是,重要的是要明白,不管垃圾收集器是什么,StopTheWorld一定是不可避免的!考生:CMS只允许GC线程和用户线程在“部分”GC场景下并发执行考生:CMS的设计目标是避免“老年代GC”出现“长期”滞后(StopTheWorld)面试官:你知道CMS的工作流程吗?考生:只知道一点点,不多。考生:CMS可以简单分为5个步骤:初始标记、并发标记、并发预清理、重标记、并发清算官:嗯……是的考生:我先从“初始标记”开始考生:”InitialMark”会标记与GCRoots“直接关联”的对象和“younggeneration”指向“oldgeneration”的对象Candidates:“initialmarking”的过程会发生StopTheWorld。但是这个阶段的速度很快,因为没有“回溯”(只有一级打分)考生:“初始打分”结束后,进入“并发打分”阶段考生:“并发打分”这个进程不会停止用户线程(StopTheWorld不会发生)。这个阶段主要是从GCRoots向下“追踪”,标记所有可达的对象。考生:从GC的角度来看,“并发标记”是比较耗时的(需要溯源)。考生:“并发标记”阶段完成后,进入“并发预处理”阶段。候选人:《Concurrentpreprocessing》这个阶段主要想做的事情:希望减少下一阶段“remarking”的时间候选人:因为下一阶段“remarking”需要StopTheWorld面试官:嗯...Candidate:"在这个阶段,由于用户线程没有被挂起,对象是一个可能发生变化的候选对象:一些对象可能会从新生代提升到老年代。有些对象可能会直接分配到老年代(大物体)。可能老年代或者新生代中的对象引用发生了变化……面试官:那这个问题怎么解决呢?考生:对于老年代中的对象,其实可以使用类卡表存储(将老年代对象变化对应的卡页标记为脏)。“并发标记”时引起老年代变化的对象会再次扫描标记为脏的卡片,过程中是否有引用老年代的对象?考生:但是JVM给我们提供了很多“参数”,在这个过程中有可能会触发minorGC(触发minorGC意味着在新生代中较少遍历对象)考生:经过“并发预处理””阶段结束,进入“remarking”阶段考生:“remarking”阶段会StopTheWorld,这个过程的停顿时间其实很大程度上取决于上面的“并发预处理”阶段(可以发现这是一个追赶过程:在标记存活对象的同时,用户线程在执行垃圾)候选:最后是“并发清除”阶段,不会停止世界候选:用户线程正在执行,GC线程正在回收无法访问的对象。考生:在这个过程中,还是有可能用户线程在不断的产生垃圾,但是只能留给下一次GC去处理。产生的垃圾Candidates称为“浮动垃圾”:完成后会重置CMS算法相关的内部数据,为下一次GC循环做准备。面试官:嗯,我了解CMS的回收流程。面试官:听着,其实就是把垃圾回收的过程“细分”,然后在某些阶段,可以在不停止用户线程的情况下,回收用户线程,同时回收垃圾和处理请求,从而减少每次垃圾收集期间StopTheWorld的时间。面试官:当然,中间做了很多优化(脏卡标记,中途可能触发minorgc等,我的理解,这些应该是提供了CMS相关的参数配置)面试官:不过,我觉得很多公司现在在用G1。那么您认为CMS的缺点是什么?候选:1.需要预留空间:CMS垃圾回收器在回收垃圾的同时可以处理用户线程,所以在这个过程中需要保证足够的内存空间供用户使用。考生:如果CMS运行时预留空间不够,会报错(ConcurrentModeFailure)。这时会启动SerialOld垃圾收集器进行老年代的垃圾收集,会造成长时间的停顿。候选项:很明显,预留多少空间,参数配置肯定有候选项:2.内存碎片问题:CMS本质上是一个实现了“markandclearalgorithm”的收集器(从流程上可以看出来),这会意味着会产生内存碎片候选项:由于碎片太多,可能会导致内存空间不足触发fullGC,CMS一般会对触发fullGC的进程进行碎片整理。考生:碎片整理涉及“移动”/“标记”,那么这个过程肯定会停止TheWorld。如果内存足够大(意味着可能加载了足够多的对象),那么这个过程会花费一定的时间。面试官:嗯……考生:使用CMS的缺点好像是死循环:考生:1、内存碎片过多,导致空间利用率降低。候选:2.空间本身需要为用户线程预留,现在碎片化的内存加剧了空间的问题,导致垃圾收集器有可能降级为SerialOld,导致freeze时间变长。考生:3.处理内存碎片(defragmentation)的问题,也会freeze了解这个过程。面试官:你了解G1垃圾收集器吗?你再也受不了了。本文概要:CMS垃圾收集器的设计目的:为了避免“老年代GC”(StopTheWorld)中的“长”滞后CMS垃圾收集器收集过程:初始标记、并发标记、并发预处理、重新标记和并发清理。初始标记和重新标记两个阶段将停止WorldCMS垃圾收集器的缺点:会产生内存碎片&&需要空间预留:停顿时间不可预测。欢迎关注我的微信公众号【Java3y】聊聊Java面试,在线面试官系列持续更新中!【在线面试官-手机版】系列,每周两篇,持续更新中!【在线面试官-电脑】系列每周两篇持续更新中!原创不易!!一连求三!!
