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.hqwc.cn/news/539758.html

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

相关文章

基于微信小程序的作业管理系统的设计与实现【附项目源码】分享

基于微信小程序的作业管理系统的设计与实现: 源码地址:https://download.csdn.net/download/qq_41810183/88842836 一、引言 随着移动互联网的普及和微信小程序的广泛应用,教育领域也在积极探索如何利用这些新技术提升教学质量和效率。本需…

基于word2vec 和 fast-pytorch-kmeans 的文本聚类实现,利用GPU加速提高聚类速度

文章目录 简介GPU加速 代码实现kmeans聚类结果kmeans 绘图函数相关资料参考 简介 本文使用text2vec模型,把文本转成向量。使用text2vec提供的训练好的模型权重进行文本编码,不重新训练word2vec模型。 直接用训练好的模型权重,方便又快捷 完整…

工具篇--从零开始学Git

一、git概述 1.1安裝 windows版本 官方下载(比较慢):Git - Downloads Linux版本 ​yum install git查看git版本。 git --version 1.2创建仓库gitee 注册账号 Gitee - 基于 Git 的代码托管和研发协作平台 新建仓库 honey2024 配置 git confi…

安装kibaba

官方地址:Past Releases of Elastic Stack Software | Elastic 直接下载就可以 安装好了之后开始配置文件/kibana/config打开kibanba.yml server.port:5601 服务器地址 sercer.name:kibana 服务器名称 kibana.index:.kibana 索引 elasticsearch.hosts:[http://1…

Kafka是什么,以及如何使用SpringBoot对接Kafka

系列文章目录 上手第一关,手把手教你安装kafka与可视化工具kafka-eagle 架构必备能力——kafka的选型对比及应用场景 Kafka存取原理与实现分析,打破面试难关 防止消息丢失与消息重复——Kafka可靠性分析及优化实践 Kafka是什么,以及如何使用…

mysql 主从延迟分析

一、如何分析主从延迟 分析主从延迟一般会采集以下三类信息。 从库服务器的负载情况 为什么要首先查看服务器的负载情况呢?因为软件层面的所有操作都需要系统资源来支撑。 常见的系统资源有四类:CPU、内存、IO、网络。对于主从延迟,一般会…

Gitlab光速发起Merge Request

前言 在我们日常开发过程中需要经常使用到Merge Request,在使用过程中我们需要来回在开发工具和UI界面之前来回切换,十分麻烦。那有没有一种办法可以时间直接开发开工具中直接发起Merge Request呢? 答案是有的。 使用 Git 命令方式创建 Me…

3dmax导入模型渲染过亮---模大狮模型网

在3ds Max中导入模型后渲染过亮可能是由于以下原因导致的: 材质和贴图设置: 检查导入的模型的材质和贴图设置,确保它们没有过度亮度或反射。调整材质的Diffuse(漫反射)颜色和Specular(高光)属性,以使渲染看起来更加自然。 光源设…

操作系统——中断

目录 前置知识 ​编辑 基本概念 1.中断特点 2.PSW(程序状态字,Program statement word) 中断的作用 中断的类型 中断嵌套、中断优先级、中断屏蔽 中断响应过程 前置知识 内核程序 :内核是操作系统的核心部分&#xff…

封装、继承、多态

1.封装 1.1 概念 举个例子解释,我们使用计算机时,并不关心内部核心部件,而是只需要知道如何开机,如何通过键盘鼠标与计算机进行交互即可.因此厂家在出厂计算机时,在外部套上壳子将内部实现细节隐藏起来,仅仅对外提供开机等,让用户可以与计算机进行交互即可. 封装: 将数据和…

14.WEB渗透测试--Kali Linux(二)

免责声明:内容仅供学习参考,请合法利用知识,禁止进行违法犯罪活动! 内容参考于: 易锦网校会员专享课 上一个内容:13.WEB渗透测试--Kali Linux(一)-CSDN博客 netcat简介内容:13.WE…

log4cplus在Qt linux中的应用与问题解决

log4cplus在Qt linux中的应用与问题解决 背景log4cplus下载遇到问题:libm.so.6:undefined reference to __strtof128_nanGLIBC_PRIVATE‘解决方案编译生成在Qt工程里面添加对应依赖编译运行成功 背景 最近工作中需要用到log4cplus的日志做一些记录,用了…