什么是三色标记?
为啥需要三色标记呢? 相比之前的标记清除算法,其GC执行期间需要把整个程序完全暂停,不能异步执行GC操作。对实时性要求比较高的系统来说,这种需要长时间挂起的标记清除算法是不可接受的,而三色标记算法就很好的解决了这个问题。 三色标记最大的好处是可以异步执行,从而可以以中断时间极少的代价或者完全没有中断操作来进行整个GC。 三色标记具体指那三色? 白色、灰色和黑色。 黑色:根对象,或者该对象与它的子对象都被扫描过。 灰色:对象本身被扫描,但是还有没扫描该对象的子对象。 白色:未被扫描的对象,如果扫描完成所有对象之后,最终为白色的为不可达对象,即垃圾对象。
并发出现“对象消失”问题
什么时候,会产生对象消失“的问题”,即原本应该是黑色的对象被误标为白色?
当且仅当以下两个条件同时满足: 赋值器插入了一条或多条从黑色对象到白色对象的新引用; 赋值器删除了全部从灰色对象到该白色对象的直接或间接引用。
那如何解决并发扫描时对象消失问题?
只需要破坏这两个条件任意一个即可,两种解决方案:增量更新(Increamental Update)和原始快照(Snap shot At The Begining, SATB) CMS 基于 增量更新(Increamental Update)来做并发标记,G1 基于 原始快照(Snap shot At The Begining, SATB)来实现的。 增量更新(Increamental Update):当一个白色对象被黑色对象引用,将黑色对象重新标记为灰色,让垃圾回收器重新扫描。 原始快照(Snap shot At The Begining, SATB):原始快照要破坏的是第二个条件,当灰色对象要删除指向白色对象的引用关系时,就将这个要删除的引用记录下来,在并发扫描结束之后,再将这些记录过得引用关系中的灰色对象为根,重新扫描一次。总而言之就是:无论引用关系删除与否,都会按照刚刚开始扫描的那一刻的对象图快照来进行搜索。 对比增量更新和原始快照: 原始快照关注的是引用删除,增量更新关注的是引用增加。 为啥G1不使用增量更新算法呢? 因为使用增量更新算法,那变成灰色的对象还要重新扫描一遍,效率太低了,所以G1在处理并发标记的过程比CMS效率要高,这个主要是解决漏标的算法决定的。