JVM 并发 GC - 三色标记

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

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

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

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

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

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

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

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

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

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

  • 增量更新
  • 原始快照

增量更新

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

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

原始快照

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

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

相关推荐
888CC++15 小时前
栈上分配 VS 堆分配 核心区别
java·开发语言·jvm
发现一只大呆瓜16 小时前
Vite 开发预构建机制详解,搞懂 esbuild 与 Rollup 分工差异
前端·面试·vite
计算机魔术师16 小时前
【AI面试八股文 Vol.3.4:训练微调部署选型】从预训练到量化部署:LLM 工程落地如何做模型选择
人工智能·后端·面试·架构·moe·vol.3.3·vol.3.4
Cosolar18 小时前
收藏备用!2026 年所有主流 RAG 开源项目都在这里了
人工智能·面试·llm
AI人工智能+电脑小能手18 小时前
【大白话说Java面试题 第69题】【JVM篇】第29题:GC Roots 有哪些?
java·开发语言·jvm·面试
图码18 小时前
二分查找进阶:如何在有序数组中快速找到Upper Bound?
数据结构·算法·面试·分类·柔性数组
Yeats_Liao19 小时前
物联网接入层技术剖析(三):epoll在JVM中的映射
java·linux·jvm·人工智能·物联网
plainGeekDev20 小时前
Kotlin核心:空安全都搞不明白,还敢说熟练Kotlin?
android·面试·kotlin
Cosolar20 小时前
从零搭建本地 RAG 系统:LangChain + LM Studio 完整实战指南
人工智能·后端·面试
罗超驿21 小时前
20.MySQL事务隔离级别示例详解(脏读、不可重复读、幻读)
java·数据库·mysql·面试