浅谈CMS和G1垃圾收集器
2023-02-10 13:34:59 16 举报
浅谈CMS和G1L集收集器
作者其他创作
大纲/内容
CMS(Concurrent Mark Sweep)收集器(-XX:+UseConcMarkSweepGC(old))
第一个实现让垃圾收集线程和用户线程同时工作的垃圾收集器
老年代采用标记清除算法
运作流程
初始标记:暂停所有的其他线程(STW),并记录下GC root直接能引用的对象,速度很快
并发标记:从GC root直接关联对象向下遍历对象,可以和用户线程一起并发运行
重新标记:修正并发标记期间,产生变动的那一部分对象的标记记录,三色标记中的增量更新算法
并发清理:开启用户线程,同时开始GC清理没有被标记的区域
并发重置:重置本次GC中标记的数据
CMS优点:
并发收集,低停顿
CMS缺点:
CMS收集器对处理器资源非常敏感,CMS默认启动的回收线程数是(处理器核心数量+3)/4,也就是说,如果处理器核心数在四个或以上,并发回收时垃圾收集线程只占用不超过25%的处理器运算资源,但是当处理器核心数量不足四个时,
CMS对用户程序的影响就可能变得很大,处理器要分出一半的运算能力去执行收集器线程,吞吐量会大大降低。
CMS对用户程序的影响就可能变得很大,处理器要分出一半的运算能力去执行收集器线程,吞吐量会大大降低。
解决方案:虚拟机提供了一种称为“增量式并发收集器”(Incremental Concurrent Mark Sweep/i-CMS)的CMS收集器变种,在并发标记、清理的时候让收集器线程、用户线程交替运行,尽量减少垃圾收集线程的独占资源的时间,减少了对用户线程的影响,但是增加了垃圾回收的时间,效果一般,JDK9发布后被废弃。
CMS无法处理浮动垃圾,执行过程中可能一边回收,一边再次触发full gc, 也就是"concurrentmode failure",此时会进入stop the world,用serial old垃圾收集器来回收
解决方案:预留一部分空间供并发收集时的程序运作使用。在JDK5的默认设置下,CMS收集器当老年代使用了68%的空间后就会被激活,,可以适当调高参数-XX:CMSInitiatingOccu-pancyFraction的值来提高CMS的触发百分比,降低内存回收频率,获取更好的性能。到了JDK 6时,CMS收集器的启动阈值就已经默认提升至92%。
标记-清除算法会产生大量的碎片
解决方案:然通过参数-XX:+UseCMSCompactAtFullCollection可以让jvm在执行完标记清除后再做整理
G1收集器(-XX:+UseG1GC)
面向服务器的垃圾收集器,主要针对配备大容量内存的机器,满足GC停顿时间要求,还需要具备高吞吐量性能特征
G1收集器的运作流程
初始标记(initial mark,STW):暂停所有的其他线程,并记录下gc roots直接能引用的对象,速度很快;
并发标记(Concurrent Marking):同CMS的并发标记
最终标记(Remark,STW):同CMS的重新标记
筛选回收(Cleanup,STW):筛选回收阶段首先对各个Region的回收价值和成本进行排序,根据用户所期望的GC停顿时间(可以用JVM参数 -XX:MaxGCPauseMillis指定)来制定回收计划
回收算法主要用的是复制算法,将一个region中的存活对象复制到另一个region中,这种不会像CMS那样回收完因为有很多内存碎片还需要整理一次,G1采用复制算法回收几乎不会有太多内存碎片
G1垃圾收集分类
YoungGC:回收时间远远小于参数 -XX:MaxGCPauseMills 设定的值,那么增加年轻代的region,继续给新对象存放,不会马上做YoungGC,直到下一次Eden区放满,G1计算回收时间接近参数 -XX:MaxGCPauseMills 设定的值,那么就会触发Young GC
MixedGC:不是FullGC,老年代的堆占有率达到参数(-XX:InitiatingHeapOccupancyPercent)设定的值则触发,回收所有的Young和部分Old(根据期望的GC停顿时间确定old区垃圾收集的优先顺序)以及大对象区,主要使用复制算法,需要把各个region中存活的对象拷贝到别的region里去,拷贝过程中如果发现没有足够的空region能够承载拷贝对象就会触发一次Full GC
Full GC:停止系统程序,采用单线程进行标记、清理和压缩整理,好空出来一批Region来供下一次MixedGC使用
G1的优点:
并行与并发:G1能充分利用CPU、多核环境下的硬件优势,使用多个CPU(CPU或者CPU核心)来缩短StopThe-World停顿时间。
分代收集:虽然G1可以不需要其他收集器配合就能独立管理整个GC堆,但是还是保留了分代的概念。
空间整合:G1从整体来看是基于“标记整理”算法实现的收集器;从局部上来看是基于“复制”算法实现的
可预测的停顿:G1 除了求低停顿外,还能建立可预测的停顿时间模型,能让使用者明确指定在一个长度为M毫秒的时间片段(通过参数"-XX:MaxGCPauseMillis"指定)内完成垃圾收集。
G1缺点:
G1使用卡表处理跨代指针实现更为复杂,堆中每个Region,无论扮演的是新生代还是老年代角色,都必须有一份卡表,这导致G1的记忆集(和其他内存消耗)可能会占整个堆容量的20%乃至更多的内存空间,由于G1对写屏障的复杂操作需要消耗更多的运算资源,G1就不得不将其实现为类似于消息队列的结构,把写前屏障和写后屏障中要做的事情都放到队列里,然后再异步处理。
解决方案:大于8内存使用G1垃圾收集器
为什么说8G以上应该用g1而不是用ParNew+CMS?
这是由于ParNew+CMS是将内存分配为年轻代和老年代。只有当内存满了才会进行gc,使用8G以上的内存就会导致一次gc要清理的垃圾实在太多了,会导致CMS进行垃圾收集时,并发标记和并发清理的时间太长,用户线程也在同时进行,导致一次回收没有结束,再次触发fullGC,stw进行单线程回收
G1则将内存分成多个大小相等region块,使用复制算法,提升效率,在大内存的情况下,G1的记忆集合其他内存消耗,占领堆的比例也会降低,还能建立可预测的停顿时间模型,控制垃圾回收的时间
0 条评论
下一页