这篇文章主要介绍JVM的CMS垃圾收集器,以及JVM提供的垃圾收集算法。
一、垃圾收集算法
垃圾收集算法JVM提供的三种垃圾收集算法,都是基于"分代收集理论"而展开的。分代收集理论主要是根据对象存活周期的不同,将内存划分为两块,分别是年轻代和老年代,然后再根据各个年代的特点去选择合适的垃圾收集算法。
标记复制算法:
标记复制算法将可用的内存划分为大小相同的两块,每次只使用其中的一块。当使用的这块内存存放满之后,就将存活的对象复制到另一块内存中,然后再把使用过的内存空间一次清理掉。但是这个算法最大的缺点就是将可用的内存缩小为原来的一半,另一半始终要空闲着用于存放存活的对象。
标记复制算法
标记清除算法:
算法分为"标记"和"清除"两个阶段,在标记阶段,将存活的对象标记起来,然后回收所有没有标记的对象;也可以反过来,标记垃圾对象,然后回收所有已标记的垃圾对象。
标记清除算法存在两个明显的缺点:
1、如果存活对象过多,那么标记的效率将十分低下
2、在清除垃圾对象后,内存将出现大量的碎片空间
标记清除算法
标记整理算法:
根据老年代的特点而出现的一种标记算法,在"标记"阶段仍然跟"标记清除算法"的标记阶段一样,但是后续并不是直接清理垃圾对象,而是将存活的对象向内存的一端移动,然后清理掉内存边界以外的空间。
标记整理算法
二、CMS垃圾收集器
CMS(Concurrent Mark Sweep)收集器,是一款以获取最短停顿时间为目标的垃圾收集器。这款垃圾收集器非常注重用户体验时间,是HopSpot虚拟机第一款真正意义上的并发垃圾收集器,实现了用户线程和垃圾回收线程同时执行。
2.1 CMS的工作流程
CMS垃圾收集器使用"标记清除"算法实现垃圾回收,它的工作流程相对而言比较复杂,主要有如下几个步骤:
1.初始标记:此阶段会暂停所有的用户线程(STW),记录gc roots能直接引用的对象,速度很快
2.并发标记:此阶段就是从gc roots直接引用对象开始遍历整个对象图的过程,这个过程耗时较长,但是可以和用户线程一起执行,但是对于已经标记对象的状态可能会发生改变
3.重新标记:此阶段主要就是为了修正在并发标记阶段,因用户线程运行,而导致已标记对象状态改变的那一部分对象的标记记录,主要就是处理漏标问题。这个阶段也是需要停止用户线程的,这个阶段会比并发标记阶段运行时间短。
4.并发清理:此阶段用户线程和垃圾回收线程同时执行,然后会回收垃圾对象
5.并发重置:重置本次GC过程标记的数据
2.2 CMS垃圾收集器的缺点
CMS垃圾收集器的主要优点为并发执行、低延迟。
同样,CMS的缺点也非常显而易见:
1.因为垃圾收集线程和用户线程会同时执行,因此会和用户线程争抢CPU资源
2.在并发标记和并发清理阶段,产生的浮动垃圾无法处理
3.CMS使用标记清除算法,会导致大量的内存碎片产生
4.执行过程的不确定性,可能会在本次GC还没执行完,又触发了一次GC,一边回收,一边程序还在运行,就会导致FullGC的发生,也就是"concurrent mode failure",此时将进入stop the world,然后转为serial Old单线程老年代垃圾收集器回收。
2.3 CMS相关的核心参数
1.-XX:+UseConcMarkSweepGC:启用cms
2.-XX:+UseCMSCompactAtFullCollection:FullGC之后做压缩整理(减少碎片),针对标记清除算法的优化
3.-XX:CMSFullGCsBeforeCompaction:多少次FullGC之后压缩一次,默认是0,代表每次FullGC后都会压缩一次
4.-XX:CMSInitiatingOccupancyFraction: 设置老年代的阈值,当达到阈值时会触发Full GC,默认时92%
三、垃圾收集器底层算法之三色标记
首先来谈谈为什么JVM要引入三色标记,我们知道在并发标记过程,因为用户线程还在执行中,那么在这个阶段,对象之间的引用关系可能就会发生改变,而关系的改变,就表明有些对象将变成垃圾对象,而有些垃圾对象又会变成正常的对象。对于这样的问题,就是多标和漏标的问题,而为了解决多标和漏标,就需要引入三色标记算法。
三色标记的原理:将gc roots可达性分析遍历对象中遇到的对象,按照是否访问过,分为三种颜色。
1.黑色:表示这个对象已经被垃圾收集器访问过,并且这个对象的所有引用也已经全部被扫描过
2.灰色:表示这个对象已经被垃圾收集器访问过,但是这个对象至少还要一个引用没有被扫描过
3.白色:白色是默认的颜色,代表没有被垃圾收集器访问过,在分析结束后如果还是白色,代表不可达,也就是垃圾对象
多标浮动垃圾:在并发标记过程中,因用户线程运行,导致部分gc roots被销毁,但是这个gc roots相连的对象又都被扫描过,那么本轮GC便不会回收这部分对象,而这部分本该回收的对象,却没有回收,就成为了浮动垃圾。
漏标:漏标问题就是严重的bug,会将正常的对象误认为是垃圾对象,这个bug是要被解决的,而解决的方案有两种:增量更新(Incremental Update) 和原始快照(Snapshot At The Beginning,SATB)。
1.增量更新:当黑色对象要新增指向白色对象的引用时,先将这个新增的引用记录起来,当扫描结束后,再将记录引用的黑色对象为根,重新扫描。也就是说,当黑色对象新增指向白色对象的引用时,黑色对象就变成了灰色对象。
2.原始快照:当灰色对象要删除指向白色对象的引用时,先将这个要删除的引用记录起来,当扫描结束后,再将记录引用的灰色对象为根,重新扫描,这样就能扫描到白色对象,然后将白色对象标为黑色。这里主要的目的还是防止误删除,现将白色变为黑色,也就成了浮动垃圾,等到下次gc时再去处理。
四、总结
CMS是一款以获取最短停顿时间为目标的老年代垃圾收集器,主要优点就是并发执行、低延迟,执行流程为初始标记、并发标记、重新标记、并发清理、并发重置。
网友评论