当前位置: 首页 > 后端技术 > Java

cms垃圾收集器

时间:2023-04-01 19:05:46 Java

cms参数:UseConcMarkSweepGC:使用cms垃圾收集器CMSFullGCsBeforeCompaction:多次fullgc排序压缩一次Default0UseCMSInitiatingOccupancyOnly:假设没有该参数,仅当cmsgc第一次发生时,jvm后参数值的CMSInitiatingOccupancyFraction会被使用会动态调整CMSInitiatingOccupancyFraction:意思是当内存使用达到一定程度时,CMS会启动GC。默认值为92%。CMSScavengeBeforeRemark:在CMSGC之前启动一次ygc。80%的GC时间花费在remark阶段)CMSScheduleRemarkEdenSizeThreshold、CMSScheduleRemarkEdenPenetration,默认值分别为2M和50%。两个参数组合意味着预清洗后,当eden空间使用量超过2M时,可以中断并发预清洗,当eden空间使用量达到50%时中断,进入remarking阶段。cmsgc触发时机:阈值检查机制:老年代的已用空间达到一定阈值,JVM默认值为92%(jdk1.5之前为68%,jdk1.6之后为92%),也可以通过CMSInitiatingOccupancyFraction和UseCMSInitiatingOccupancyOnly有两个参数需要设置;该参数的设置取决于应用场景。如果设置得太小,会导致频繁出现CMS。如果设置太大,会导致并发模式失败过多。比如动态检查机制:JVM会根据最近的回收历史来预估下一次老年代耗尽的时间,并在这个时间临近时开始并发循环。可以通过设置参数UseCMSInitiatingOccupancyOnly来关闭此功能。fullgc触发时机:1:System.gc()。如果没有启用,则禁止调用system.gc()DisableExplicitGC;2:提升失败:这种情况一般是在对象即将提升到老年代的时候,发现老年代内存不足,于是触发了FullGC。对象的提升分为正常提升(存活15代)和早期提升(大对象放不下存活区)。3:并发模式失败:CMSGC执行过程中,同时有对象要放入老年代,此时老年代不足。4:MetaSpace空间不够5:jmap-dump:live触发CMS退化为串行gc情况:提升失败不会导致CMS在fullGC中退化为serialGC并发模式失败会导致FullGC。这种情况下会用到SerialOld收集器,它是单线程的,对GC影响很大。CMSGC过程:CMSGC只回收堆的旧区域。1:初始标记:在这个阶段,需要STW。这个过程从根集开始,只扫描和标记可以与根集直接关联的对象。jdk1.8之后这一步是并发的。这里的根集不包含年轻代。2:并发标记:该阶段跟在初始标记阶段之后,在初始标记的基础上继续向下追溯标记。在并发标记阶段,应用线程和并发标记线程是并发执行的,所以用户不会有停顿的感觉。3:Pre-cleaning阶段:这个阶段会处理并发标记过程中eden区变化的引用(具体来说就是eden指向oldgen的引用变化),同时也会处理dirtycard中的引用。4:可中断预清理阶段:这个阶段主要处理from和to区域对象的oldgen引用的变化,同时也继续处理dirtycard的对象引用。触发条件:Eden区占用>CMSScheduleRemarkEdenSizeThreshold(默认2M),中断条件:Eden区占用>CMSScheduleRemarkEdenPenetration(默认50%),或达到5秒。5:备注:STW扫描根集,其中包含年轻代。CMSremark需要重新扫描mod-union表中的dirtycard加上整个rootset,此时整个younggen(不管object是dead还是alive)都会被认为是rootset的一部分,所以CMS的评论可能会很慢。6:并发清理:清理垃圾对象。在这个阶段,收集器线程和应用程序线程并发执行。7:并发重置:在这个阶段,重置CMS收集器的数据结构,等待下一次垃圾收集。CMS的Precleaning(预清洗)和AbortablePreclean(可中断预清洗)预清洗和可中断预清洗不是必须的,可以通过参数XX:-CMSPrecleaningEnabled关闭。空闲链表空间:cmsgc回收会产生不连续的内存,用链表将它们连接起来,当用户请求分配时,系统从可用空间表中删除一个节点进行分配;当用户释放占用的内存时,系统回收并插入到可用空间表中。三色标记方式:黑色:从GCRoots开始,它引用的所有对象都被扫描过,标记为黑色灰色:对象本身已经被扫描过,它引用的所有对象都没有被完全扫描过,标记为灰色白色:未扫描白色三色标记漏标问题原因:漏标会导致本该存活的对象被回收。标记后至少有一个黑色物体指向这个白色物体。所有灰色对象都通过它们自己的参考进行扫描。在CMS处理INC屏障完成之前删除了对白色对象的引用:如果一个黑色对象添加了一个白色对象,则黑色对象变灰。这样重新标记的时候会继续扫描他。这有一个缺陷:ConcurrentMark期间无法在堆外找到对根集(寄存器、堆栈)的引用更改。为此,在concurrentmark之后,需要一个remark阶段,然后STW再次扫描rootset。