关于G1,CMS,SATB,增量更新这些概念我就不废话了,如果学习了JVM,我相信这些概念不是什么问题,这里我只说一下在学习过程中,糊涂了很长时间之后又通透了的地方。
相信大家都知道,CMS和G1在并发标记的时候采用了三色标记的方法,但是这种标记在并发的情况下会有漏标的问题。
CMS
先说CMS,CMS采用的是增量更新的方法,也就是说CMS只关心引用的增加,不关心引用的删除,我用图片举一个例子:
CMS在进行并发标记的时候,n和a之间的引用断开了,但是1和a之间的引用增加了,这时候,CMS记录了1和a之间的应用关系,再次进行GC扫描的时候,重新从添加引用的地方进行扫描,也就是从1重新扫描,扫描的结果是a和1之间有应用关系,所以不是垃圾。但是CMS的这种方式会有一个问题,那就是耗时,我们从图中可以看到,1后面有n多个引用关系,甚至是一个非常发散的树状,重新从1扫描是非常耗时的。
G1
G1的方式和CMS不一样,G1只记录删除关系,增加的引用不关心。我们还是看上面的图片,当n和a断开前,G1会生成一个引用快照,然后删除引用关系,并且把a变为灰色,这里需要注意:并不是因为a和1之间增加了引用关系才变为灰色的,即便是a没有任何的应用关系,也会变为灰色,也就是说,a有可能是浮动垃圾,不过在引用上没有任何问题,只是让浮动垃圾多存活一次GC扫描而已。a变为灰色后,G1进行最终标记,从快照信息中拿到n和a的应用,重新进行扫描。所以这种方式要比CMS节省扫描时间
我这里不太确认的是a对象,总觉得G1采用这种方式会有很多浮动垃圾,虽然在下次初始标记时会被清除,但是总觉得有点问题。