JVM - 三色标记算法

880 阅读2分钟

三色标记

  • 三色标记
  • Incremental Update write barrier
  • STAB(Snapshot-at-beginning)

三色标记过程

假设内存初始状态如下图,在标记前 白色为所有对象的默认状态 ,在标记完成后 白色对象则为垃圾数据需要清理 image.png

将A 和 E 已经标记完成 但是还未标记A和E的引用 所以灰色代表对象本身已经标记 但未标记对象所引用的值

image.png

A A1 A2 C D E 将自己以及自己本身引用的对象全部标记过 那么A A1 A2 C D E则为黑色 image.png

漏标问题

在并发标记的时候 会产生漏标问题如下图

image.png

在A2为灰色的时候 应用程序线程删除了A2-> C的引用
同时增加了 黑色D(黑色代表全部标记完成的对象)引用了白色C的对象

此时就会产生C漏标 因为D是黑色 标记线程认为D已经标记完成 而A2已经删除了C对象 这个时候C对象从A2已经不可达 故C漏标

incremental update write barrier(增量写屏障)

这里的屏障不是指JMM中的内存屏障 而是另外一中实现逻辑称之为屏障

增量写屏障

增量写屏障也是CMS垃圾回收器采用的方式,但是会产生浮动垃圾具体的可以查看CMS浮动垃圾,主要原因是因为增量增量的意思就是记录在并发阶段记录引用增加的关系 这里主要说明漏标,浮动垃圾会在CMS中详细说明

在黑色对象需要访问白色对象的时候 也就是 黑色对象添加了白色对象引用的时候,会将本来为黑色对象的值变更为灰色对象。
以下图为例 就是将 D变更为了灰色,那么在此扫描的时候 会将D重新扫描 就可以访问到C了

image.png

SATB

snapshot-at-the-beginning 在GC执行的时候 如果发生了修改对象引用关系,那么垃圾回收器会记录删除对象的引用,这样可以达到 关系引用图是固定的(快照实现),当并发标记的时候 程序改变了某个对象的引用,会将该对象 的引用,存储至一个队列中(satb_mark_queue),后续再次遍历的时候 可以直接从队列中找到修改过的引用,从而方便重新标记 这个会在G1的垃圾回收器中说明G1垃圾回收器写屏障

image.png