在遍历对象图的过程中,把需要遍历的对象按照“是否访问过”分为以下三种颜色。
- 白色:表示对象尚未被垃圾回收器访问过。显然,在可达性分析刚刚开始的阶段,所有的对象都是白色的,若在分析结束的阶段,仍然是白色的对象,即代表不可达。
- 黑色:表示对象已经被垃圾回收器访问过,且这个对象的所有引用都已经扫描过。黑色的对象代表已经扫描过,它是安全存活的,如果有其它的对象引用指向了黑色对象,无须重新扫描一遍。黑色对象不可能直接(不经过灰色对象)指向某个白色对象。
- 灰色:表示对象已经被垃圾回收器访问过,但这个对象至少存在一个引用还没有被扫描过。
- 如果不保障一致性,对象会消失。
如何解决这个问题?
一个叫Wilson的大佬,他在1994年在理论上证明了,当且仅当以下两个条件同时满足时,会产生"对象消失"的问题,原来应该是黑色的对象被误标为了白色:- 条件一:赋值器插入了一条或者多条从黑色对象到白色对象的新引用。
- 条件二:赋值器删除了全部从灰色对象到该白色对象的直接或间接引用。
- 增量更新(Incremental Update):打破了第一个条件,在扫描过程中,如果黑色对象插入了新的白色对象引用,那么就将这些黑色对象记录起来作为GC Roots,在扫描结束的时候重新扫描以这些为Root的引用链。其实就可以很简单的理解成,在黑色对象插入新的白色对象引用以后,就重新变成了灰色对象。
- 原始快照(Snapshot At The Beginning,SATB):打破了第二个条件。在扫描过程中,如果出现灰色对象删除白色对象的引用时,就将这些灰色对象记录下来。在扫描结束后,对这些灰色对象重新扫描一遍。
- 增量更新使用的是写后屏障(记录插入后的新引用)
- 原始快照使用的是写前屏障(记录删除后的前引用)