三色标记-垃圾收集器底层算法

2023-11-15

三色标记

前言

三色标记相信大家也有所耳闻,但是都没有过深入的了解。小编在之前和同事交流的过程中,了解到很多大厂在问虚拟机问题的时候会问到三色标记的问题。所以想再今天和大家分享一下自己对三色标记的理解。如果有理解的有问题的地方,欢迎大家指正。那么就让我们进入三色标记的学习中吧!


提示:以下是本篇文章正文内容,下面案例可供参考

一、三色标记是什么?

三色标记算法是把在Gc Root可达性分析算法遍历对象的过程中,遇到的对象进行“黑,灰,白”三种颜色的标记。
三色标记操作的阶段是在CMS的并发标记阶段,因为用户的线程也在执行,所以已经标记的对象的引用可能会发生变化。**多标和漏标**的情况都会发生,漏标主要是通过三色标记算法来解决的。

二、三色的介绍

1.黑色

黑色表示对象已经被垃圾收集器访问过,并且这个对象的所有引用都被扫描到了。黑色对象代表已经扫描过,是安全存活的,如果有其他对象的引用指向黑色的对象,不需要重新扫描。

2.灰色

灰色表对象已经被垃圾收集器访问过,但是这个对象的部分引用未被访问到。

3.白色

白色表示对象还没有被垃圾收集器访问过。显然处于可达性分析的初始阶段,如果可达性分析已经结束了,对象还是标记为白色则认为这个对象的垃圾对象。

在这里插入图片描述

上图关系的维护都在并发标记阶段维护,在重新标记阶段处理,这两种方式都是处理漏标的情况

  1. 在上图中对象A到对象D新增关联关系,在HotSpot虚拟机中会新增一个写屏障,用于记录新增关系,内部维护的是一个集合。当在重新标记的阶段,就会扫描整个集合。也就是三色标记中的增量更新
  2. 在上图中对象B到对象D删除了关联关系,在HotSpot虚拟机中会新增一个写屏障,用于记录对象间删除的关系。在重新标记阶段,扫描集合,将删除的对象直接标记为黑色(浮动垃圾),等待下次Gc再去回收。这个是三色标记中的原始快照

三、浮动垃圾

浮动垃圾的产生在下一次Gc过程中再去标记收集

  1. 在并发标记阶段,如果运行的方法结束,栈帧被销毁,栈帧中的局部变量作为Gc Root遍历的引用对象集在之前标记为非垃圾对象,但是实际上目前是垃圾对象。本轮的并发清除阶段不会被清除。这类被称为浮动垃圾
  2. 在并发标记和并发清除阶段,新生成的对象会被直接标记成黑色,等待下次Gc再被回收。这类也称为浮动垃圾
  3. 在并发标记阶段,如果对象之间的关系发生了删除,这时候虚拟机内部通过写屏障维护一个集合,这个集合在重新标记阶段会把所以删除关系的引用对象,设置成黑色。这类也是浮动垃圾

四、读写屏障

1.为什么HotSpot虚拟机需要提供一个读写屏障呢?带着疑问去学习我们能了解的更快。

读写屏障主要解决的问题是漏标的问题。漏标对象会导致对象被当成垃圾回收掉。这对于任何程序都是很严重的BUG。必须要解决。因此HotSpot虚拟机为我们提供了两种方案来解决这个问题:增量更新和原始快照

  1. 增量更新:增量更新就是在黑色对象插入新的白色对象的引用时,就把这个引用记录下来。等并发扫描后,重新以黑色对象为根开始扫描整个引用链。也可以理解为当黑色对象插入新的白色引用时,会变成灰色。
  2. 原始快照:原始快照就是在灰色对象要删除白色对象的引用时,就把这个引用记录下来。等扫描结束后,将记录中的引用关系为灰色的为根进行再次扫描,将扫描到的白色对象直接设置成黑色。(产生的浮动垃圾在下次Gc的时候再去收集)

2.以上引用关系的新增和删除,都是通Hotspot虚拟机的写屏障实现的


3.说了那么多,那么写屏障在HotSpot虚拟机中到底是如何实现的呢?

所谓的写屏障,其实就是在赋值阶段的前后,加入一些操作。(思路可以参考Spring中的AOP)

void oop_field_store(oop* field, oop new_value) {  
    pre_write_barrier(field);          // 写屏障-写前操作
    *field = new_value; 
    post_write_barrier(field, value);  // 写屏障-写后操作
}

写屏障实现STAB,在写前记录下原来的引用对象。

void pre_write_barrier(oop* field) {
    oop old_value = *field;    // 获取旧值
    remark_set.add(old_value); // 记录原来的引用对象
}

写屏障实现增量更新,在写后记录下对象间新增引用。

void post_write_barrier(oop* field, oop new_value) {  
    remark_set.add(new_value);  // 记录新引用的对象
}

四、总结

CMS垃圾收集器并发收集阶段漏标的解决方案:写屏障+增量更新
后面我还会介绍G1垃圾收集器的原理,和CMS垃圾收集器还是有很多相似的地方。这边小小的透露下G1垃圾收集器在并发扫描阶段出现了漏标会采用:写屏障+原始快照的方案。

那么为什么G1会选择这种方案呢?大家可以思考一下。顺带大家在思考一个阿里的面试题:为什么G1要选择使用原始快照,而cms选择使用增量更新呢?

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

三色标记-垃圾收集器底层算法 的相关文章

随机推荐

  • qemu-guest-agent windows下的监控开发

    windows下的qemu guest agent 简称qga 的名字叫做qemu guest agent win32 目前最新版的版本号是qemu guest agent win32 0 12 1 2 2 355 el6 4 9 x86
  • 【踩坑】三种方式解决 Homebrew failing to install - fatal: not in a git directory

    问题描述 解决方法一 添加安全目录 没有测试 git config global add safe directory opt homebrew Library Taps homebrew homebrew git config globa
  • 动手写docker中遇到的问题合集

    fork exec usr bin sh operation not permitted exit status 1 我的环境 win10 wsl2 ubuntu20 04 解决方案 设置wsl默认用户为root sudo nano etc
  • java实现赫夫曼树以及赫夫曼编码和解码(用byte[])

    首先对于赫夫曼编码有个大概的理解 赫夫曼编码 Huffman Coding 又称霍夫曼编码 是一种编码方式 可变字长编码 VLC 的一种 Huffman于1952年提出一种编码方法 该方法完全依据字符出现概率来构造异字头的平均长度最短的码字
  • ubuntu搭载网络文件系统与linux开发板共享资源

    搭建NFS 如果ubuntu是运行在虚拟机上的 首先需要修改ubuntu与windows的网络连接模式 将其修为桥接模式与windows连接网络 ubuntu以及开发板安装net toos sudo apt install net tool
  • 常用设计模式-命令模式

    命令模式 讲一个请求封装成一个对象 可以让不同的请求对客户进行参数化 对请求排队或者记录请求日志 以及支持可撤销的操作 别名为事务模式或者动作模式 这样两者之间通过命令对象进行沟通 这样方便将命令对象进行储存 传递 调用 增加与管理 命令模
  • QFile创建文件以及递归文件删除文件

    QFile创建文件 1 t dir mkpath t firstFilePath 创建文件夹 2 t File open QIODevice WriteOnly QIODevice Truncate 创建文本 3 若文件不存在会创建一个 Q
  • mybatis-plus入坑指南

    简介 MyBatis Plus 简称 MP 是一个 MyBatis 的增强工具 在 MyBatis 的基础上只做增强不做改变 为简化开发 提高效率而生 特性 无侵入 只做增强不做改变 引入它不会对现有工程产生影响 如丝般顺滑 损耗小 启动即
  • python用matplotlib画折线图

    折线图 import matplotlib pyplot as plt y1 10 13 5 40 30 60 70 12 55 25 x1 range 0 10 x2 range 0 10 y2 5 8 0 30 20 40 50 10
  • java设计模式--[创建模式]--抽象工厂[abstract factory]

    抽象工廠 提供一個接口 用於創建相關或依賴對象的家族 而不需要指定具體類 二 設計某些系統是坷以南非要為用戶提供一系列相關的的對象 但系統不希望用戶真接使用new 運算符實例化這些對象 而由系統來控制這些對象的創建 否則用戶不僅要清楚地知道
  • 推荐系统架构

    推荐系统架构 实际推荐系统通常采用多种推荐算法 并根据用户的实时行为反馈调整用户的特征向量 特征的加权系数 进而融合各个推荐算法的推荐结果 在此基础上过滤不要的推荐项 最后结合用户使用场景调整推荐结果排名 给出最终推荐结果 基于不同特征的推
  • STM32F030 USART2配置函数 波特率不对导致无法进入中断

    今天调试STM32F030 USART2 收发不了数据 仿真的时候进入不了中断 但是配置也是正确的 搞了很久 原因是先初始化的串口再初始化Flash数据 导致读入的波特率是0 进而无法正常使用USART2 浪费了大量的时间 血的教训呀 vo
  • 【保姆级教学】搭建win10系统 IIS Web 服务器(上)

    先确认计算机上是否已安装 IIS 1 进入Windows10的控制面板 点击 系统和安全 2 找到 管理工具 并点击 3 查看是否有Internet Information Services IIS 管理器 如图 我的计算机已经安装好了 注
  • Python——Numpy高级索引

    Python Numpy高级索引 整数数组索引 或 与索引数组组合 布尔索引 比较运算符 取补运算符号 np iscomplex 过滤非复数元素 花式索引 传入顺序 倒序索引数组 使用 np ix 传入多个索引数组 https editor
  • MySQL——MySQL的介绍、安装、卸载与使用

    1 介绍 MySQL数据库隶属于MySQL AB公司 总部位于瑞典 后被oracle公司收购 优点 成本低 开放源码 可免费使用 性能高 执行很快 简单 容易安装和使用 DBMS分为两类 基于共享文件系统的DBMS Access 基于客户机
  • torch.max函数比较最大值

    新建两个tensor列表 利用torch max 进行两个列表的比较 import torch a torch tensor 1 2 3 4 5 print a a b torch tensor 10 1 7 9 3 print b b x
  • 认识HTTP请求

    要分析HTTP请求和响应必然少不了抓包工具 关于抓包工具的设置和下载推荐看抓包工具Fiddler的下载与设置 通过抓包得到的一个HTTP请求 HTTP请求的格式 结构分析 一 请求行 1 post是方法 可以表示一条HTTP请求要进行的操作
  • elementui的el-input校验正则表达式

    el input 只能输入正整数 包括0 在 Input 值改变时触发 handleEdit e let value e replace d g 只能输入数字 value value replace 0 d 1 第一位0开头 0后面为数字
  • 前后端分离之Springboot

    这里写目录标题 springboot后台搭建 1 创建父项目 1 1 创建netseal 2 创建子项目 2 1 创建webserver 2 2 创建common 3 正式编码 3 1 修改pom文件 3 1 1 netseal的pom x
  • 三色标记-垃圾收集器底层算法

    三色标记 文章目录 三色标记 前言 一 三色标记是什么 二 三色的介绍 1 黑色 2 灰色 3 白色 三 浮动垃圾 四 读写屏障 四 总结 前言 三色标记相信大家也有所耳闻 但是都没有过深入的了解 小编在之前和同事交流的过程中 了解到很多大