这是我参与8月更文挑战的第10天,活动详情查看:8月更文挑战
首先我们重温知识点
判断对象失是否存活
==两种判断方法==
引用计数算法
- 在对象中添加一个引用计数器,每当有一个地方引用它时
- 计数器值就加一;当引用失效时,计数器值就减一;
- 任何时刻计数器为零的对象就是不可能再被使用的。 ==引用计数算法的缺陷==
- 如下面代码,两个对象互相引用导致无法回收♻️
- 对象objA和objB都有字段instance,赋值令 objA.instance=objB及objB.instance=objA,
- 除此之外,这两个对象再无任何引用,实际上这两个对象已 经不可能再被访问,
- 但是它们因为互相引用着对方,导致它们的引用计数都不为零,引用计数算法也 就无法回收它们。
Test objA = new Test();
Test objB = new Test();
objA.instance = objB;
objB.instance = objA;
objA = null;
objB = null;
可达性分析算法
==基本思路==
- 通过一系列称为“GC Roots”的根对象作为起始节点集,从这些节点开始,根据引用关系向下搜索,
- 搜索过程所走过的路径称为“引用链”(Reference Chain),如果某个对象到GC Roots间没有任何引用链相连,
- 或者用图论的话来说就是从GC Roots到这个对象不可达时,则证明此对象是不可能再被使用的。
三色标记📌
有三种颜色
-
白色:代表对象还没有被垃圾收集器访问过,最开始所有都是白色,但是在结束阶段,如果还是白色,那么就不可达
-
黑色:代表对象已经被垃圾收集器访问过,并且所有引用已经被扫描过,是安全存活的
-
灰色:代表对象已经被垃圾收集器访问过,但是这个对象至少存在一个引用还没被扫描过
-
最初的状态:只有GC Roots是黑色的
- 扫描过程中,从黑色变为灰色
- 扫描完成后,黑色就是活着的对象,白色就是已经消亡可以回收♻️
- 但是如果现在用户线程在标记进行时并发修改了引用关系,灰色的引用被断开,又与黑色对象建立了引用
- 切断以后黑色对象,因为黑色对象不会重新扫描,这样就会扫描结束后,被黑色引用的依然是白色,这个对象就「消失了」
对象消失情况
- 当插入一条或多条从黑色对象到白色对象的新引用
- 删除了全部从灰色到白色的直接或间接引用
两种解决方案
增量更新
- 破坏第一个条件,当有黑色对象新的引用白色对象时,就把插入的引用记录下来,
- 等并发扫描过后,再讲这些记录的应用关系中的黑色对象作为跟,重扫一遍
- 其实可以理解成黑色对象一旦插入了只想白色对象的引用后,就变为灰对色象了,因为要让它保证继续扫 原始快照
- 破坏第二个条件,要是有灰色要删除指向白色引用关系时,就将这个删除引用记录下来
- 等并发扫描结束后,再将灰色对象为根,重扫一遍
- 可以理解为记录删除引用,再以灰为根去扫