JVM垃圾回收——三色标记法
目录
一、什么是三色标记
二、三色标记的过程
三、三色标记的缺点
四、垃圾回收机如何弥补三色标记的缺点
在CMS、G1这种并发的垃圾收集器收集对象时,假如一个对象A被GC线程标记为不可达对象,但是用户线程又将A对象标记为可达对象,那么此时直接对A对象做清除时那将会发生很严重的错误,那么对象A是如何摆脱被清除的命运呢?今天就简单来聊聊这个问题。
一、什么是三色标记
主流的垃圾收集器基本上都是基于可达性分析算法来判定对象是否存活的。根据对象是否被垃圾收集器扫描过而用白、灰、黑三种颜色来标记对象的状态的一种方法。而其中
- 白色:表示对象尚未被垃圾收集器访问过。显然在可达性分析刚刚开始阶段,所有的对象都是白色的,若在分析结束之后对象仍然为白色,则表示这些对象为不可达对象,对这些对象进行回收。
- 灰色:表示对象已经被垃圾收集器访问过,但是这个对象至少存在一个引用(属性)还没有被扫描过。
- 黑色:表示对象已经被垃圾收集器访问过,且这个对象的所有引用都已经被扫描过。黑色表示这个对象扫描之后依然存活,是可达性对象,如果有其他对象引用指向了黑色对象,无须重新扫描,黑色对象不可能不经过灰色对象直接指向某个白色对象。
二、三色标记的过程
初始状态
初始阶段只有GC Roots是黑色的,其他对象都是白色的,如果没有被黑色对象引用那么最终都会被当做垃圾对象回收。
开始扫描
A和B均为扫描过的对象并且其引用也已经被垃圾回收器扫描过所以此时A、B对象均变为了黑色,而刚扫描到对象C,由于C的D和E还没有被扫描到,所以C暂时为灰色。
顺利扫描结束
此时扫描完成,黑色对象就是存活的对象,即可可达对象,白色对象G为不可达对象,在垃圾回收时就会被回收掉。
三、三色标记的缺点
我们知道CMS和G1等垃圾回收器是一个并发回收的垃圾回收器,上面的图片只是展示了一种理想状态下的三色标记,实际上在并发的情况下会存在多标和漏标的问题。
场景
假如GC线程已经扫描到了E对象,此时E对象为灰色,这个时候用户线程将C的引用E断开,那么GC就会认为E对象是可达对象,而不会对E进行垃圾回收,但实际上E是个垃圾对象,这个时候就会产生多标问题,多标问题其实还可以接受,E作为浮动垃圾,那么等到下次垃圾回收的时候回收掉。
场景
假如用户线程先断开了C到E的引用,那么E对象就认为是不可达对象,而此时B对象又引用了E对象,但是三色标记又不会重新从B点开始标记到E,那么E就会被认为是垃圾对象,但实际上E是有引用的,那么此时对E进行垃圾回收,之后就一定会产生错误,这就是漏标问题。
四、垃圾回收机如何弥补三色标记的缺点
上面演示了三色标记法存在的一些问题,那么如何解决这些问题呢。首先存在以上问题有两个条件同时满足才会发生
- 赋值器插入了一条或者多条从黑色对象到白色对象的引用。
- 赋值器删除了所有的从灰色对象到白色对象的直接引用或者间接引用。
那么要想解决并发扫描时对象消失的问题只需要破坏任何一个条件即可。因此产生了两种解决方案——增量更新(Incremental Update)和原始快照(Snapshot At The Beginning, SATB)。
增量更新破坏的是第一个条件,当黑色对象插入新的指向白色对象的引用关系时。就将这个新插入的引用记录下来,等并发扫描结束之后,再将这些记录过的引用关系中的黑色对象作为根对象,再重新扫描一遍。比如漏标问题中,一旦B对象直接指向了E对象,那么在并发扫描之后,就会将B对象作为灰色对象,再重新扫描一遍。这样虽然避免了漏标问题,但是重新标记会导致STW的时间变长。
原始快照破坏的是第二个条件,当灰色对象要删除指向白色对象的引用关系时,就将这个要删除的引用记录下来,在并发扫描结束之后再将这些记录过的引用关系中的灰色对象为根对象再重新扫描一遍。例如漏标问题的途中,C断开E的引用关系时会保存一个快照,然后等扫描结束之后,会把C当作根再重新扫描一遍,假如B没有引用E,那么E对象也会认为是可达对象,这样E就成了浮动垃圾,只能等下次垃圾回收时再回收。
无论是对引用关系记录的插入还是删除,虚拟机的记录操作都是通过写屏障实现的。在HotSpot虚拟机中,CMS是基于增量更新来做并发标记的,G1、Shenandoah则是用SATB来实现的。
JVM垃圾回收——三色标记法相关推荐
- 垃圾回收之三色标记法
关于垃圾回收算法,基本就是那么几种:标记-清除.标记-复制.标记-整理.在此基础上可以增加分代(新生代/老年代),每代采取不同的回收算法,以提高整体的分配和回收效率. 无论使用哪种算法,标记总是必要的 ...
- 【七天入门Go语言】 GC垃圾回收三色标记 | 第七天
目录 GC 三色标记法 最后 GC GC全称Garbage Collection 目前主流的垃圾回收算法有两类,分别是追踪式垃圾回收算法(Tracing garbage collection)和引用计 ...
- JVM垃圾回收——G1垃圾收集器
目录 一.什么是G1垃圾收集器 二.G1垃圾收集器的内存划分 三.G1垃圾收集器的收集过程 四.G1收集器的优缺点 五.G1收集器的JVM参数配置 一.什么是G1垃圾收集器 Garbage First ...
- 内存管理篇(三):Go垃圾回收之三色标记算法
三色标记法介绍: 三色标记法(tricolor mark-and-sweep algorithm)是传统 Mark-Sweep 的一个改进,它是一个并发的 GC 算法,在Golang中被用作垃圾回收的 ...
- 简明易懂的JVM垃圾回收理解
文章目录 写在前面 垃圾回收(GC)的概念 垃圾回收判断 垃圾回收区域 对象是否可以被回收 垃圾回收搜索根 GC Roots 安全点 Safepoint 垃圾回收的时刻 垃圾回收算法 标记-清除算法 ...
- 双/三色标记法的垃圾回收(GC)原理解析和缺陷解决方案(Go,Lua以及jvm的CMS和G1垃圾回收器中使用的回收算法)
标记-清除算法 go和lua虚拟机以及jvm的CMS和G1垃圾回收器的回收算法的思想均来自于标记-清除算法(Mark-Sweep),它们的gc有重要的两部分: 1.从根节点遍历所有对象,如果可达到,则 ...
- golang 垃圾回收、三色标记法、写屏障
垃圾回收简称 GC,就是对程序中不再使用的内存资源进行自动回收释放的操作. 常见的垃圾回收算法 引用计数:每个对象维护一个 引用计数,当对象被创建或被其他对象引用时,计数 +1:如果引用该对象的对象被 ...
- 浅谈垃圾对象回收之《三色标记法》
文章目录 前言 什么是垃圾回收 JAVA的垃圾回收回顾 GO的垃圾回收学习 **三色标记法(tricolor mark-and-sweep algorithm)** Dijkstra方法(插入屏障,强 ...
- 详细图解JVM三色标记法
文章目录 为什么要使用三色标记法? 三色标记法中的三色 三色标记的漏标问题 如何解决漏标问题? CMS 增量更新(Incremental Update) G1 原始快照(Snapshot At The ...
最新文章
- WMI技术介绍和应用——查询桌面信息
- python基础代码事例-数据科学Python基础(附示例代码和练习题目)
- mybatis基本增删改查、缓存,延迟加载以及别名的配置
- [luoguP2774] 方格取数问题(最大点权独立集)
- (2.15)备份与还原--使用作业备份、清理过期备份、清理历史记录、事务日志是否备份过...
- 如何查看Windows 10的具体版本号?
- 「一道面试题」ArrayList和LinkedList有什么区别及使用场景
- 《iOS 6核心开发手册(第4版)》——1.13节秘诀:从滚动视图中拖动
- 初学者Pytorch 和 Caffe 使用对比
- Listary使用技巧
- 机电传动控制 第三周作业
- C语言随机产生26个大写字母
- 使用Apple第三方登录Java版
- autojs通知栏_监听通知栏失败,请教大佬!
- 数据圈最全的数据分析产品文章合集
- pythonopencv提取轮廓区域_Python + Opencv 实现轮廓提取,轮廓区域面积计算
- linux 内核2.6.35.3,linux-2.6.35.3内核移植(s3c2440)
- python写水仙花的作文_怎样背英语单词才高效?
- 解密excel工作表打开密码
- 国仁网络:揭秘成为“网红”背后的艰辛道路,达人不签约MCN的10个理由。