JVM 并发 GC - 三色标记

垃圾收集就意味着需要进行可达性算法,但是在执行可达性算法时,当前的 JVM 内部需要保持一个禁止的状态,也就是其他的用户线程不允许进行操作,所有的用户线程需要等到垃圾收集结束后才能开始继续执行,这意味着用户的体验感可能会非常地差:用户可能正在访问某个页面时,JVM 突然开始垃圾回收,如果当前 Java 堆内对象较少,那用户可能会怀疑是自己的网络原因,但是如果已经达到了十分庞大的对象量,用户就会看着加载页面转啊转,甚至弹出页面暂时无法访问。这个时候并发处理就十分重要了。

并发的可达性分析算法 - 三色标记

在三色标记算法中,对象会被标记为三种颜色之一:

  • 白色:表示对象尚未被访问,可能是垃圾。
  • 灰色:表示对象已被访问,但其引用的对象尚未全部访问。
  • 黑色:表示对象及其所有引用的对象都已访问。

但是如果是在并发地进行并发的可达性算法时,用户线程突然对某个将要被删除、并且已经被标记了的对象进行了操作,我们假设所有对象都没有重写 finalize (毕竟 Java 官方不推荐使用),那么这个对象可能刚好被引用,但是下一秒就又被删除了,这样子导致错误。

https://shipilev.net/talks/javazone-Sep2018-shenandoah.pdf

Wilson 在 1994 年在理论上证明了,当且仅当以下两种条件都满足时,会产生"对象消失"问题

  • 赋值器插入了一条或多条从黑色对象到白色对象的引用
  • 赋值器删除了全部从灰色对象到白色对象的直接或间接引用

即:当前对象还未被扫描,当前对象被已经被扫描过并且标记了不会有其他引用对象的对象引用

因此,想要解决并发扫描时对象消失问题,只需要破坏这两种条件的其中一种即可

  • 增量更新
  • 原始快照

增量更新

增量更新破坏的是 "赋值器插入了一条或多条从黑色对象到白色对象的引用" 条件

当对黑色对象插入新的指向白色对象的引用关系时,就将这个新插入的引用记录下来,在并发扫描后,再将这些记录过的引用关系中的黑色对象为根,再重新扫描一次,可以简单理解为:只要黑色对象插入新的指向白色对象的引用,黑色对象就会变成灰色对象

原始快照

当灰色对象要删除指向白色对象的引用关系时,就将这个要删除的引用记录下来,在并发扫描结束之后再将这些记录过的引用关系中的灰色对象为根,重新扫描一次。可以简单理解成:无论引用关系删除与否都会按照刚刚开始扫描的那一刻的图像快照来进行搜索

简单来说,增量更新和原始快照都在一次可达性算法过后对更新过的节点进行扫描以达到不会产生"对象消失"的目的

相关推荐
触底反弹1 小时前
深入理解大模型采样:Temperature、Top-K、Top-P 的原理与实战
人工智能·算法·面试
沉默王二3 小时前
腾讯一面,我霸气反问:“你说你们在做Agent项目,说说 SubAgent、Plan 模式、Skill 调用这些你们都是怎么做的?”面试官一直在擦汗。。
面试·agent·ai编程
白露与泡影5 小时前
Arthas 实战指南:从方法耗时定位到 JVM 变量热修改
服务器·jvm·c#
程序员Rock7 小时前
上位机开发-MODBUS面试常见问题
c语言·c++·面试·职场和发展·上位机
Ai_easygo7 小时前
MCP 协议实战:用 Claude Desktop 连本地 SQLite,5 分钟搭一个能查数据的 AI 助手
jvm·人工智能·sqlite
PBitW11 小时前
git 中容易遗忘的点 (二) ⚡⚡⚡
前端·git·面试
浩哥学JavaAI11 小时前
2026年最新AI agent面试(07)_大模型架构基础
人工智能·面试·架构
PBitW11 小时前
git 中容易遗忘的点 (三) 🚀🚀🚀
前端·git·面试
十八岁牛爷爷13 小时前
C/C++ 六大关键字(static、const、volatile、extern、register、inline)面试三层级详解
开发语言·c++·面试
胡萝卜术13 小时前
抽象的三级跳:从原生 DOM 到 React 组件树,我们到底在解决什么问题?
前端·javascript·面试