java垃圾回收-三色标记法

三色标记法

  • 引言
  • 什么是三色标记法
    • 白色
    • 灰色
    • 黑色
  • 三色标记过程
  • 三色标记带来的问题
    • 多标问题
    • 漏标问题
  • 如何弥补漏标问题
    • 增量更新
    • 原始快照
    • 总结

引言

在CMS,G1这种并发的垃圾收集器收集对象时,假如一个对象A被GC线程标记为不可达对象,但是用户线程又把A对象做清楚时 将会发生严重的错误,那么jvm是如何处理这种问题呢?

什么是三色标记法

主流的垃圾收集器基本上都是基于可达性分析算法来判断对象是否存活的,根据对象是否被垃圾收集器扫描过而用黑白灰三种颜色来标记对象状态的方法。

白色

表示对象尚未被垃圾收集器扫描过。在可达性分析开始阶段,所有的对象都是白色的。若在分析结束后对象仍是白色,则代表对象为不可达对象,需要对这些对象进行回收。

灰色

表示对象已经被垃圾回收器访问过,但这个对象至少存在一个引用还没被扫描过。

黑色

表示对象已经被垃圾收集器访问过,且这个对象的所有引用都已经扫描过。 黑色的对象代表已经被扫描过,他是安全存活的,如果有其他对象引用指向了黑色对象,无需重新扫描一遍。黑色对象不可能直接指向某个白色对象。

三色标记过程

  1. 在gc线程开始标记的时候,所有的对象都是白色,全部放入白色节点集合中。
    在这里插入图片描述

  2. 然后从gc root set开始进行扫描,首先node1,node5 被扫描到,node 1、5被标记成灰色节点,从白色节点集合中挪到灰色节点集合中。
    注意,这里只遍历一次root set集合,不是递归遍历。
    在这里插入图片描述

3, 然后gc会从灰色节点开始继续向下扫描,也就是从node1,node5(被标记成灰色的节点)开始,然后扫描到node2,node6 会被标记成灰色,然后node2,node6从白色集合挪到灰色集合。然后node1,node5因为已经被扫描过了会被标记成黑色,然后从灰色几点挪到黑色节点结合中。
在这里插入图片描述

  1. 继续从灰色节点node2,node6开始往下遍历,因为node2,node6已经被扫描过了,所以会被标记成黑色节点,从灰色节点挪到黑色节点集合中。
    node3节点被标记成灰色节点,从白色节点挪到灰色节点集合中。
    在这里插入图片描述

  2. 继续从灰色节点node3开始遍历,直到最终没有了灰色节点就不会再往下遍历了,因为Node3被遍历过了,所以会被标记为黑色,从灰色集合中挪到黑色集合中。最终只会剩下两种状态的节点(只有黑色和白色)。
    在这里插入图片描述

  3. 最终回收完垃圾节点就只只剩下标记成黑色状态的节点,这就是整个过程。

三色标记带来的问题

因为cms和g1垃圾回收器是一个并发回收的回收器,标记线程和用户线程是并发执行的,那么就有可能在标记过程中,用户线程修改了对象的引用关系,造成多标,或者漏标。那么针对这些问题jvm又是怎么处理的呢?

多标问题

在这里插入图片描述

  • 假如gc线程已经扫描到了对象e,此时e为灰色,说巧不巧这个时候用户现成ObjectC.e=null, 将c的引用e断开了。
  • 因为e是灰色,gc就会认为e对象是可达对象,而不会对e进行回收,但实际上e是个浮动垃圾,但实际上还可以接受,因为等到下次垃圾回收的时候可以回收掉。
  • 但并不代表就不是缺点,如果浮动垃圾较多,可能触发full gc。

漏标问题

在这里插入图片描述
假如用户线程断开了c到e的引用,那么e对象就是不可达对象,而此时b对象又引用了e对象,但是三色标记又不会重新从b点开始标记到e,那么e就会被认为是垃圾对象,但实际e是有引用的。如果对e进行垃圾回收,就会产生错误,这就就漏标问题。

如何弥补漏标问题

我们仔细观察漏标,会发现,这种场景的出现是有条件的,

  • 黑色对象被插入了一条或者多条白色引用。
  • 灰色对象删除了白色对象的引用。

可以归结为:

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

因此,只要侦查到这2个条件的发生即可,所以产生了两种解决方案——增量更新(Incremental Update)和原始快照(Snapshot At The Beginning, SATB)。

增量更新

增量更新破坏的是第一个条件,当黑色对象插入新的指向白色对象的引用关系时。就将这个新插入的引用记录下来,等并发扫描结束之后,再将这些记录过的引用关系中的黑色对象作为根对象,再重新扫描一遍。比如漏标问题中,一旦B对象直接指向了E对象,那么在并发扫描之后,就会将B对象作为灰色对象,再重新扫描一遍。这样虽然避免了漏标问题,但是重新标记会导致STW的时间变长。

原始快照

原始快照破坏的是第二个条件,当灰色对象要删除指向白色对象的引用关系时,就将这个要删除的引用记录下来,在并发扫描结束之后再将这些记录过的引用关系中的灰色对象为根对象再重新扫描一遍。例如漏标问题的途中,C断开E的引用关系时会保存一个快照,然后等扫描结束之后,会把C当作根再重新扫描一遍,假如B没有引用E,那么E对象也会认为是可达对象,这样E就成了浮动垃圾,只能等下次垃圾回收时再回收。

总结

无论是对引用关系记录的插入还是删除,虚拟机的记录操作都是通过写屏障实现的。在HotSpot虚拟机中,CMS是基于增量更新来做并发标记的,G1、Shenandoah则是用SATB来实现的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/745362.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MySQL 常见用法练习

LIMIT [参数1]--m,参数2--n; #表示从跳过m条数据开始取n行数据 #参数1为可选参数,表示跳过m条数据(默认为0) eg:1表示从第二行开始 #参数2为必选参数,表示取几行数据 SELECT *FROM employees ORDER BY hire_date DESC LIMIT 1; SELECT *FROM employees ORDER BY hire…

数字化经济的前沿:深入了解 Web3 的商业模式

随着区块链技术的迅速发展,Web3作为一种新型的互联网范式,正逐渐引起人们的关注。它不仅仅是一种技术革新,更是一种商业模式和价值观的转变。本文将深入探讨Web3的商业模式,以及它对数字化经济的影响。 1. 理解Web3的商业模式 We…

解决 Java 错误 Unreachable Statement

本篇文章介绍了 Java 中的 unreachable statement 错误。 Java中出现 unreachable statement 错误的原因 当我们尝试在分支控制流语句之后放置语句时,会发生不可到达语句错误。 分支语句包括 break、continue 和 return,它们用于跳转到代码的不同部分。…

go get x509:certificate signed by unknown authority

概述 在arm设备上构建golang 1.22的Docker镜像,用来做程序的编译镜像,直接安装用ubuntu作为基础镜像,构建好的镜像,在编译的时候执行go get的时候,会报下面错误 go: github.com/***: Get "https://goproxy.cn/g…

Qt教程3-Ubuntu(x86_64)上配置arm64(aarch64)交叉编译环境及QT编译arm64架构工程

详见: Qt教程3-Ubuntu(x86_64)上配置arm64(aarch64)交叉编译环境及QT编译arm64架构工程

算法---滑动窗口练习-4(无重复字符的最长子串)

无重复字符的最长子串 1. 题目解析2. 讲解算法原理3. 编写代码 1. 题目解析 题目地址:点这里 2. 讲解算法原理 算法的主要思想是使用滑动窗口来维护一个不含重复字符的子串。定义两个指针 left 和 right 分别表示窗口的左边界和右边界。还定义了一个数组 hash 来记…

华为认证云计算专家(HCIE-Cloud Computing)–单选题

华为认证云计算专家(HCIE-Cloud Computing)–单选题 13.( 单选)WAF服务属于以下哪个安全子领域() A 应用安全 B 数据安全 C 主机安全 D 安全管理 E 网络安全 正确答案:A 24 (单选题)以下关于非容灾,Global与Region融合部署场景&…

redis配置文件详情

redis自带两个conf配置文件,redis.conf为redis配置文件,sentinel.conf为哨兵配置文件。 注意:修改配置文件需要重启生效。 一、redis.conf为redis的配置文件 # redis进程是否以守护进程的方式运行,yes为是,no为否(不…

Apache Paimon 的 CDC Ingestion 概述

CDC Ingestion 1)概述 Paimon支持schema evolution将数据插入到Paimon表中,添加的列将实时同步到Paimon表,并且无需重启同步作业。 目前支持的同步方式如下: MySQL Synchronizing Table: 将MySQL中的一个或多个表同步到一个Pa…

【算法与数据结构】深入解析二叉树(一)

文章目录 📝数概念及结构🌠 树的概念🌉树的表示🌠 树在实际中的运用(表示文件系统的目录树结构) 🌉二叉树概念及结构🌠概念🌉数据结构中的二叉树🌠特殊的二叉…

Spring web MVC(2)

1、RequestMapping称为路由映射(既是类注解也是方法注解提供访问路径) 2、RequestParam起到重命名的作用,也起到绑定的作用,传递集合list时会用到,多个值绑定给list,默认是必传参数如果不传参数需要设置re…

如何在Windows 10上打开和关闭平板模式?这里提供详细步骤

前言 默认情况下,当你将可翻转PC重新配置为平板模式时,Windows 10会自动切换到平板模式。如果你希望手动打开或关闭平板模式,有几种方法可以实现。​ 自动平板模式在Windows 10上如何工作 如果你使用的是二合一可翻转笔记本电脑&#xff0…

Spring, SpringBoot, SpringCloud,微服务

1,SSM (Spring+SpringMVC+MyBatis) SSM框架集由Spring、MyBatis两个开源框架整合而成(SpringMVC是Spring中的部分内容),常作为数据源较简单的web项目的框架。 Spring MVC 是 Spring 提供的一个基于 MVC 设计模式的轻量级 Web 开发框架,本质上相当于 Servlet,Controlle…

vue 基于elementUI/antd-vue, h函数实现message中嵌套链接跳转到指定路由 (h函数点击事件的写法)

效果如图: 点击message 组件中的 工单管理, 跳转到工单管理页面。 以下是基于vue3 antd-vue 代码如下: import { message } from ant-design-vue; import { h, reactive, ref, watch } from vue; import { useRouter } from vue-router; c…

PY32离线烧录器功能介绍,可批量烧录,支持PY32系列多款单片机

PY32离线烧录器可以对PY系列单片机进行批量烧录,现支持PY32F002A/002B/002/003/030/071/072/040/403/303芯片各封装和XL2409,XL32F001/003等芯片。PY32离线烧录器需要搭配上位机软件才能使用,上位机软件在我们官网(www.xinlinggo.…

代码随想录刷题第60天

最后一题了。最后一题是柱状图中最大的矩形https://leetcode.cn/problems/largest-rectangle-in-histogram/,和接雨水遥相呼应的一道题,我们需要找到当前遍历数字左右两边第一个小于当前数字的值,通过保证单调栈中数字为递减顺序,…

Hive集合函数 collect_set 和 collect_list 使用示例

Hive集合函数 collect_set 和 collect_list 使用示例 在Hive中, collect_set 和 collect_list 是用于收集数据并将其存储为集合的聚合 函数。以下是它们的语法: 1. collect_set(expression)- expression : 要收集的数据表达式。collect_set 函数用于将…

【软考】UML中的图之对象图

目录 1. 说明2. 图示3. 特性 1. 说明 1.对象图即object diagram2.展现了某一时刻一组对象以及它们之间的关系3.描述了在类图中所建立的事物的实例的静态快照4.对象图一般包括对象和链5.对象图展示的是对象之间关系,不存在交互,所以不是交互图 2. 图示 …

#微信小程序(一个emo文案界面)

1.IDE:微信开发者工具 2.实验:一个emo文案界面 (1)最好使用rpx (2)图片宽度占不满,在CSS中设置width为100% (3)imag图片全部为网页链接图片 3.记录 4.代码 index.htm…

【基础计算机网络2】物理层——物理层设备

【前言回顾】 【考纲内容】 物理层设备:中继器;集线器 一、物理层设备 1.1 中继器 描述:中继器是用来扩大网络规模的最简单廉价的互连设备,中继器两端的网络部分是网段,而不是子网。使用中继器连接的几个网段仍是一…