三色标记法

三色标记法(标记算法)

1.基本概念

白色(未被标记,默认)、灰色(还有引用的对象)、黑色(被标记完的)。

2.背景

原始的垃圾标记算法比如计数器法(无法解决循环依赖问题)、可达性分析法(整个分析都需要STW,停顿时间长)。

 

3.标记过程:

3.1 初始标记(Initial Marking)

  • 目标:标记从 GC Roots 直接可达的对象。
  • 过程
    • 从 GC Roots(如栈帧、静态变量、JNI 引用等)出发,标记所有直接引用的对象为 灰色
    • 这些对象会被加入待扫描队列。
  • 特点
    • 这个阶段是 停顿的(Stop-the-World),因为需要快速确定 GC Roots 的直接引用。
    • 停顿时间通常很短。

3.2 并发标记(Concurrent Marking)

  • 目标:在应用程序运行的同时,遍历所有对象图,标记所有存活对象。
  • 过程
    • 从初始标记阶段得到的 灰色 对象开始,递归遍历所有引用链。
    • 将遍历到的对象标记为 灰色黑色
    • 这个阶段是 并发执行的,不会暂停应用程序。
  • 特点
    • 由于是并发执行的,应用程序可能会修改对象图(例如新增引用或删除引用)。
    • 这可能导致 漏标多标 的问题。

3.3 重新标记(Remark)

  • 目标:修正并发标记阶段由于应用程序运行导致的标记错误。
  • 过程
    • 暂停应用程序(Stop-the-World),确保对象图不再变化。
    • 重新扫描并发标记期间可能被修改的部分:
    • 使用 写屏障(Write Barrier) 记录的对象引用变化。
    • 重新标记这些对象,确保所有存活对象都被正确标记为 黑色
  • 特点
    • 这个阶段是 停顿的,但通常比初始标记阶段长。
    • 它是并发标记的补充,确保标记结果的准确性
       

4.并发标记的写屏障

(以下两种方式:增量更新 or 原始快照)

用于记录并发标记期间对象的修改状态,如果增加了一个引用,并且没有被标记过则标记为灰色在第三阶段重新标记。

可能会发生多标,影响不大,下一次GC会清理掉。不会发生漏标。

5.漏标问题

过程:

  • A(黑)-> B (灰)-> C(白) ①初始状态

  • A(黑) -> C(白) <- B(灰) ②增加A到C

  • A(黑)-> C(白) B(灰) ③删除B到C

  • 此时C就是一个活跃对象但是将会被回收

原因及方案:

  • 至少有一个黑色对象在自己被标记之后指向了这个白色对象

    • 增量更新:检测到A->C,将C标记为灰色
  • 所有的灰色对象在自己引用扫描完成之前删除了对白色对象的引用

    • 原始快照:检测到B删除C,将C标记为灰色,最后C被扫描
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇