前言
前面的文章里讲到过JVM通过可达性分析算法进行垃圾回收,那么可达性分析算法它分析完了以后是怎样进行记录的呢,它怎么知道哪些是垃圾对象哪些不是垃圾对象呢,今天我们来讲解一下三色标记算法。下面我先介绍一下理论,但是单看理论可能太抽象,请再结合我后面的图片进行分析思考。
理论
黑色:表示对象已经被垃圾收集器访问过,且这个对象的所有引用都已经扫描过。黑色的对象代表已经扫描过,它是安全存活的。
灰色:表示对象已经被垃圾收集器访问过,但是这个对象上至少存在一个引用还没有被扫描过。
白色:表示对象尚未被垃圾收集器访问过。
图片分析
图中黑色箭头代表对象之间的引用,红色箭头代表垃圾收集器扫描的路径,第一张图因为扫描器还没有进行扫描,所以所有的对象都是白色的。
一、第一次扫描
第一次扫描到了A对象,但是A对象下面的直接引用对象还有未扫描到的对象B和对象C,所以A对象为灰色。
二、第二次扫描
第二次扫描到了B对象,但是B对象下面还有一个直接引用对象D没有被扫描到,所以B对象变为灰色,然而A对象下面有一个直接引用对象C没有被扫描到,所以A对象也还是灰色。这里再次强调一下红色连线代表扫描的路径以及扫描到的对象,黑色连线代表对象之间的引用,之所以画两个箭头引用就是为了让大家区分开箭头所代表的不同含义。
三、第三次扫描
第三次扫描从A对象扫描到了B对象,由于B对象下面没有未被扫描的对象了(因为B下面已经没有引用的对象了),所以B为黑色,而A对象也因为下面的直接引用对象B和C都已经被扫描过了,所以A也变为了黑色,而B下面的D对象还没有被扫描过,所以B还是灰色。
四、第四次扫描
第四次扫描从B扫描到了D对象,因为D对象下面没有引用对象了,所以D变为黑色了,而B下面也没有未被扫描过的对象了,所以B对象也变为了黑色,这个时候扫描器就结束扫描过程了,大家看到了扫描器并没有扫描E对象,这是因为两点,1、E对象不是GCRoot根,扫描器是从GCRoot根节点开始扫描的,也就是从图中A对象开始扫描。2、E对象没有被GCRoot根节点或者根节点引用下的节点引用,假如这个时候A、B、C、D任何一个对象引用E对象,E对象都会变为黑色,而目前图中的E对象就相当于我们在程序里面new了一个Strudent对象,但是没有任何对象使用它或者调用它,它就相当于在程序里面“悬空”了,所以垃圾收集器会在后面的垃圾收集阶段将白色的E对象收集掉,其他的对象不会收集。
总结
这里的三色标记算法并不是在程序内部真正的将对象标记成为黑色、灰色、白色,而是可能用了两个二进制位来表示,比如00表示黑色、01表示灰色、10表示白色,所以这里的三色标记算法只是为了让大家更好的理解罢了,希望大家看了我的文章可以有所收获,也希望大家多多关注我,我们一起学习进步,谢谢大家。