「这是我参与11月更文挑战的第4天,活动详情查看:2021最后一次更文挑战」
三色标记
为了更好的了解垃圾收集标记的过程,我们引入三色标记的概念。
什么是三色标记?
| 颜色 | 含义 | ||
|---|---|---|---|
| 白色 | 对象未被垃圾收集器访问过 | 可达性分析刚开始时,未被访问的对象都是白色的 | 可达性分析结束后,未被引用到的对象都是白色的 |
| 、 | |||
| 黑色 | 对象已被垃圾收集器访问过,且这个对象的引用都被扫描过 | ||
| 灰色 | 对象被垃圾收集器访问过,但存在引用对象未被扫描到 |
并发问题
当用户线程与收集器标记并发工作时,收集器标记过程中,用户线程同时修改了引用关系,会出现两种情况
- 原本需要死亡的,被标记为存活。
- 原本需要存活的,被标记为死亡。
第一种情况问题不大,下一次垃圾回收时再清理掉就好了,但是第二种情况就很严重了。
下图展示第二种情况是怎么出现的:
扫描结束后,就会导致A、B两个对象本应该存活,但被错误的标记为死亡。
解决方案
后续Wilson通过理论证明,只要同时满足以下两个条件,就会产生"本应该存活的对象却消亡"情况。
- 赋值器插入了一条或多条黑色对象到白色对象的新引用。
- 赋值器删除了所有灰色对象到该白色对象的直接或间接引用。
针对这种情况,有两种解决方案
- 增量更新
- 原始快照
- 增量更新
破坏第一个条件,当黑色对象插入新的引用到白色对象时,就记录这个引用。当本次扫描结束时,将记录过的引用关系的黑色对象为根,重新扫描一次。可以理解为只要黑色对象插入了一条引用到白色对象时,黑色对象就会变成灰色对象,进行下一次的扫描。
- 原始快照
破坏第二个条件,当灰色对象要删除指向白色对象的引用时,就记录这个引用。当本次扫描结束时,将记录过的引用关系的灰色对象为跟,重新扫描一次。
虚拟机的记录操作都是通过写屏障进行的。