JVM三色标记算法

发布于:2025-09-04 ⋅ 阅读:(15) ⋅ 点赞:(0)

一、背景

        在JVM的垃圾回收机制中,准确识别哪些对象是垃圾(即不再被引用的对象)是核心任务之一,通常采用根可达性分析算法。
        传统的垃圾回收算法如标记-清除(Mark-Sweep)、标记-整理(Mark-Compact)等在标记阶段通常会产生STW(Stop The World)方式,这会导致应用程序出现明显的停顿。为了减少这种停顿时间,JVM引入了三色标记算法,它是现代垃圾回收器(如CMS、G1、ZGC等)的核心算法之一。


二、三色的含义

三色标记算法将对象分为三种颜色,每种颜色代表不同的状态

1、白色对象

  • 定义:尚未被垃圾回收器访问到的对象
  • 初始状态:在标记开始阶段,所有对象均为白色,表示"未被发现"或"待处理"状态
  • 最终状态:标记结束后,仍然是白色的对象被视为垃圾对象,会在后续的清除阶段被回收

2、灰色对象

  • 定义:已经被垃圾回收器访问到,但该对象引用的其他对象还没有被完全扫描,表示"已发现但未处理完"状态
  • 中间状态:表示该对象正在被处理中,其部份引用已经被扫描,但还有一些引用未被扫描

3、黑色对象

  • 定义:已经被垃圾回收器访问到,并且该对象引用的所有其他对象也都已经被扫描过,表示"已处理完成"状态
  • 终结状态:黑色对象不会再被重新扫描,垃圾回收器认为其引用的所有对象都已经被标记

三、三色标记算法流程

1、初始阶段

  • 所有对象均被标记为白色

2、标记阶段

  • 根对象标记:垃圾回收器从GCRoots根对象(如 栈中的引用、静态变量引用等)开始扫描,将根对象标记为灰色
  • 灰色对象处理:依次处理每个灰色对象,将其引用的所有白色对象标记为灰色,并将该灰色对象自身标记为黑色
  • 循环处理:重复上述步骤,直到所有灰色对象都变为黑色对象为止

3、完成阶段

  • 所有对象的颜色均为黑色或白色,白色对象即为垃圾对象,会在后续的清除阶段被回收

四、漏标问题

1、漏标问题的原因

在并发标记过程中,由于用户线程和垃圾回收线程同时运行,可能会出现以下两种情况,导致对象被错误的标记为垃圾:

  • 条件一:一个白色对象(未扫描的对象)被黑色对象(已扫描的对象)引用
  • 条件二:从灰色对象到该白色对象(未扫描的对象)的直接或间接引用被破坏

当这两个条件同时满足时,由于黑色对象不会被再次扫描,而且灰色对象也无法引用这个白色对象,所以会导致白色对象被错误的标记为垃圾,这种现象称为"对象消失问题",也叫漏标。

2、漏标问题的解决方案

(1)增量更新

  • 原理:当黑色对象插入新的指向白色对象的引用时,将插入操作记录下来(通过写屏障)。在重新标记阶段,重新处理这些记录,确保白色对象被正确标记。
  • 应用场景:CMS垃圾回收器采用增量更新。

(2)原始快照

  • 原理:当灰色对象要删除指向白色对象的引用时,将这个要删除的引用记录下来。在重新标记阶段,将这些记录中的白色对象标记为灰色,确保他们不会被错误回收。
  • 应用场景:G1和ZGC采用原始快照。

网站公告

今日签到

点亮在社区的每一天
去签到