垃圾收集器ParNew&CMS与底层三色标记算法详解
2023-01-29 23:06:50 11 举报
垃圾收集器ParNew&CMS与底层三色标记算法详解
作者其他创作
大纲/内容
根据对象的存活周期将内存分为几块,jvm中分为新生代和老年代
分代收集理论
讲内存分为大小相等的两块,其中一块的内存满了,复制到另一半内存,回收另一半
标记复制算法
标记之后不是直接回收对象,而是讲所有存活的对象向一段移动,清除掉边界以外的内存
标记整理算法(适合老年代)
标记存活的对象,回收未标记对象,是最基础的收集算法
效率问题:标记的对象太多,效率不高
空间问题 :标记后会产生大量不连续的碎片
存在问题
标记清除算法(适合年轻代)
垃圾收集算法
没有万能的垃圾收集器,根据应用场景选择适合自己的垃圾收集
新生代采用复制算法UseSerialGC
老年代采用标记-整理算法UseSerialOld
没有线程交互的开销,可以获得很高的单线程收集效率
作为CMS收集器的后备方案
优点
串行收集器,最基本的垃圾收集器,进行垃圾收集工作时会STW
b style=\
新生代采用复制算法
老年代采用标记-整理算法
JDK8默认的新生代和老年代收集器:Parallel Scavenge收集器和Parallel Old收集器
是serial的多线程版本,在垃圾收集时使用多线程,减少STW时间,默认线程数和cpu核数相同,可以用参数修改,不推荐
font color=\"#b71c1c\
可以和CMS收集器配合使用
和Parallel收集器区别:
ParNew收集器(-XX:+UseParNewGC)
第一个实现让垃圾收集线程和用户线程同时工作的垃圾收集器
老年代使用标记-清除算法
初始标记:
从GC root直接关联对象向下遍历对象,可以和用户线程一起并发运行
并发标记:
修正并发标记期间,产生变动的那一部分对象的标记记录,三色标记中的增量更新算法
重新标记:
开启用户线程,同时开始GC清理没有被标记的区域
并发清理:
重置本次GC中标记的数据
并发重置:
运作过程:
并发收集,低停顿
CMS优点:
解决方案: 无
对CPU资源敏感(会和服务抢资源)
解决方案:无
无法处理浮动垃圾(在并发标记和并发清理阶段又产生垃圾,这种浮动垃圾只能等到下一次gc再清理了);
解决方案:然通过参数-XX:+UseCMSCompactAtFullCollection可以让jvm在执行完标记清除后再做整理
标记-清除算法会产生大量的碎片
执行过程中可能一边回收,一边再次触发full gc, 也就是\"concurrentmode failure\",此时会进入stop the world,用serial old垃圾收集器来回收
CMS缺点:
-XX:+UseConcMarkSweepGC:启用cms
-XX:ConcGCThreads:并发的GC线程数
-XX:+UseCMSCompactAtFullCollection:FullGC之后做压缩整理(减少碎片)
-XX:CMSFullGCsBeforeCompaction:多少次FullGC之后压缩一次,默认是0,代表每次FullGC后都会压缩一次
-XX:CMSInitiatingOccupancyFraction: 当老年代使用达到该比例时会触发FullGC(默认是92,这是百分比)
-XX:+UseCMSInitiatingOccupancyOnly:只使用设定的回收阈值(-XX:CMSInitiatingOccupancyFraction设定的值),如果不指定,JVM仅在第一次使用设定值,后续则会自动调整
-XX:+CMSScavengeBeforeRemark:在CMS GC前启动一次minor gc,目的在于减少老年代对年轻代的引用,降低CMS GC的标记阶段时的开销,一般CMS的GC耗时 80%都在标记阶段
-XX:+CMSParallellnitialMarkEnabled:表示在初始标记的时候多线程执行,缩短STW
-XX:+CMSParallelRemarkEnabled:在重新标记的时候多线程执行,缩短STW;
CMS的核心参数:
CMS(Concurrent Mark Sweep)收集器(-XX:+UseConcMarkSweepGC(old))
垃圾收集器
表示对象已经被垃圾收集器访问过, 且这个对象的所有引用都已经扫描过
黑色
表示对象已经被垃圾收集器访问过, 但这个对象上至少存在一个引用还没有被扫描过。
灰色
表示对象尚未被垃圾收集器访问过
白色
在并发标记的过程中,因为标记期间应用线程还在继续跑,对象间的引用可能发生变化,多标和漏标的情况就有可能发生。这里我们引入“三色标记”来给大家解释下,把Gcroots可达性分析遍历对象过程中遇到的对象, 按照“是否访问过”这个条件标记成以下三种颜色:
针对并发标记(还有并发清理)开始后产生的新对象,通常的做法是直接全部当成黑色
解决方案:
多标会产生浮动垃圾
黑色对象一旦新插入了指向白色对象的引用之后, 它就变回灰色对象了,重新标记时会扫描新增的引用
增量更新(IncrementalUpdate)CMS用 引用赋值操作前
当灰色对象要删除指向白色对象的引用关系时, 就将这个要删除的引用记录下来,并发扫描后将白色对象直接标记为黑色对象
原始快照(Snapshot At The Beginning,SATB)G1用 引用赋值操作后
SATB相对增量更新效率会高(当然SATB可能造成更多的浮动垃圾),因为不需要在重新标记阶段再次深度扫描被删除引用对象,而CMS对增量引用的根对象会做深度扫描,G1因为很多对象都位于不同的region,CMS就一块老年代区域,重新深度扫描对象的话G1的代价会比CMS高,所以G1选择SATB不深度扫描对象,只是简单标记,等到下一轮GC再深度扫描。
为什么G1用SATB?CMS用增量更新?
解决方案:都是虚拟机通过写屏障来实现
漏标会导致被引用的对象被当成垃圾误删除
三色标记
垃圾收集底层算法
垃圾收集器ParNew&CMS与底层三色标记算法详解
0 条评论
回复 删除
下一页