当前位置: 首页 > news >正文

标记垃圾,有三种色彩:四千长文带你深入了解三色标记算法

在这里插入图片描述

🔭 嗨,您好 👋 我是 vnjohn,在互联网企业担任 Java 开发,CSDN 优质创作者
📖 推荐专栏:Spring、MySQL、Nacos、Java,后续其他专栏会持续优化更新迭代
🌲文章所在专栏:JVM
🤔 我当前正在学习微服务领域、云原生领域、消息中间件等架构、原理知识
💬 向我询问任何您想要的东西,ID:vnjohn
🔥觉得博主文章写的还 OK,能够帮助到您的,感谢三连支持博客🙏
😄 代词: vnjohn
⚡ 有趣的事实:音乐、跑步、电影、游戏

目录

  • 前言
  • 可达性分析算法
  • 标记过程
  • 三色标记算法
    • 多标
    • 漏标
    • Compare
  • 总结

前言

回顾 优化内存利用:深入了解垃圾回收算法与回收器 一文,介绍了垃圾回收算法、垃圾收集器(垃圾收集算法是内存回收的方法论,那么垃圾收集器就是内存回收的实践者)

主要谈到了 CMS、G1 这两种垃圾收集器,它们都有一个共同的特征,可支持并发标记,从此文来介绍它们两者在并发标记阶段共同所使用的算法

可达性分析算法

当前主流编程语言的垃圾收集器基本上都是依靠可达性分析算法来判定对象是否存活的,可达性分析算法理论上要求全过程都基于一个能保障一致性的快照才能进行分析,这意味着必须全程冻结用户线程的运行

在 JVM 整个内存结构布局中,堆的大小占比是特别大的,堆越大,存储的对象就越多,对象图结构就越复杂,从而就要标记更多的对象而产生的 STW 时间就会越长

“标记阶段”是所有垃圾收集算法的共同特征,若这个阶段随着堆变大而增加停顿时间,其所有的垃圾收集器都会在这个阶段都会波及到一定影响,若能够削减这部分带来的停顿时间,收益也将会是系统性的提高

标记过程

简要回顾一下 CMS、G1 两者垃圾收集器在进行垃圾回收时所要发生的四个阶段:

  • CMS:初始标记、并发标记、重新标记、并发清除
  • G1:初始标记、并发标记、最终标记、筛选回收

CMS、G1 两者都有并发标记这个阶段,导致了它们两者在用户线程、GC 回收线程同时运行时负载会有所不同,同时也会出现一些引用标记的问题「多标、漏标」

三色标记算法

若要解决或降低用户线程的停顿,首先就会搞清楚为什么必须在一个能保障一致性的快照上同时还能进行对象图的遍历操作

能保障一致性的快照上同时还能进行对象图的遍历操作:指的就是并发标记阶段

在垃圾收集器中实践阶段,引入了 “三色标记” 算法作为辅助工具,把遍历对象图过程中遇到的对象,按照 “是否访问过” 这个条件来标记成三种不同颜色的引用对象

  1. 白色:表示对象尚未被垃圾收集器访问过,在根可达分析刚开始的阶段,所有对象都是白色的,若在标记阶段结束后,仍然是白色的对象,即代表不可达,对象就会被回收 > 处于消亡状态
  2. 黑色:表示对象以及被垃圾收集器访问过,且这个对象关联的所有引用都已经被扫描过;黑色的对象代表已经被扫描过,它是安全存活的,若其他对象引用指向了黑色对象,无须再重新扫描一遍
  3. 灰色:表示对象已经被垃圾收集器访问过,但这个对象上至少存在一个引用(属性对象)还没被扫描过

在这里插入图片描述

初始状态,只有 GC Roots 是黑色的

在这里插入图片描述

标记过程:并发垃圾收集的标记阶段过程中,灰色对象的标记状态不断向前推进,从黑色对象(已完成标记)扩展到白色对象(尚未被访问)灰色对象是黑、白对象之间的分水岭

从根对象逐步向下扫描,相当于就是在对象图上从黑向白推进「灰色对象作为黑、白两者之间的分水岭」过程,从 Serial 系列、Parallel 系列垃圾收集器来看,当出现垃圾收集时,它们的用户线程是处于冻结态的,只有垃圾收集线程是处于工作态的,就不会出现对象图很乱的问题

故而言之,Serial 系列、Parallel 系列收集器无须额外使用三色标记算法去处理,它们采用追踪式垃圾收集算法(标记-复制、标记-清除、标记-整理)处理即可

在这里插入图片描述

标记完成:标记阶段完成,此时黑色对象就是存活的对象,白色对象就是已消亡且可回收对象

可是,当使用了 CMS 或 G1 垃圾收集器(并发垃圾收集器,支持垃圾收集线程、用户线程并发执行)时,这时候情况就不一样了,垃圾收集线程会在对象图结构上进行颜色标记,同时用户线程也在修改引用关系(即修改对象图的结构)这时就会出现两种后果

多标、漏标

多标

多标:将原来消亡的对象错误标记为存活,这不是好事,增加了额外的内存空间浪费,但其实是可以容忍的,只不过产生了一些逃过本次垃圾收集产生的浮动垃圾而已,下次再进行清理即可

在这里插入图片描述

在颜色状态推进的过程中,正在扫描的黑对象引用切断与灰色对象关系(此时应已被标记为消亡态),但此时又有另外一个黑色对象将其标记了(此时又由最初的消亡态变换为存活态)

漏标

漏标:将原来存活的对象错误标记为已消亡,这种情况下就会比较严重,程序会因此发生程序错误,例如:Class Xxx Not Found

当且仅有两个条件同时满足时,会造成漏标问题的产生,即原本应当是黑色对象的被误标记为白色对象

  1. 插入了一条或多条从黑色对象到白色对象的新引用
  2. 删除了所有从灰色对象到白色对象的新引用

因此,要解决在并发标记阶段所造成的漏标问题,只需要破坏这两个条件中的任意一个条件即可,分别产生了以下两种解决方案:增量更新(Increment Update)以及原始快照(Snapshot At The Beginning -> SATB)

我们来看造成漏标问题的第一个条件是如何产生的,如下图:

在这里插入图片描述

结合第一张、第二张图来看,再看上图,在颜色状态推进的过程中,正在扫描的灰色对象引用切断与白色对象的联系,同时原来白色引用的对象又已经跟扫描过的黑对象建立了引用关系

增量更新的方案是破坏了第一个条件,当黑色对象插入新的指向白色对象关系时,就将这个新插入的引用记录下来,等待并发标记阶段结束以后的下一个阶段,再将这些新插入的引用记录,以黑色对象为根,重新扫描一次

CMS 采用的就是增量更新的方式来处理漏标问题,在它的重新标记阶段进行处理,可以简单理解为,一旦黑色对象插入了新的指向白色对象的引用,它就会变为灰色对象

我们来看造成漏标问题的第二个条件是如何产生的,如下图:

在这里插入图片描述

被切断后的对象重新被黑色对象所引用的对象可能是原有引用链中的一部分,由于黑色对象只会扫描一次,这将导致扫描结束后出现两个被黑色对象所引用的对象仍是白色,所以这两个白色对象就会消失,这种情况就很严重了

原始快照的方案就是破坏了第二个条件,当灰色对象要删除指向白色对象的引用关系时,就将这个要删除的引用记录下来,在并发标记阶段后的下一个阶段,再将这些删除的引用关系以灰色对象为根,重新进行一次扫描工作

G1 采用的就是原始快照 SATB 方式来处理漏标问题的,在它的最终标记阶段进行处理,也可以简单理解为,无论引用关系删除与否,都会按照刚开始扫描的那一刻对象图快照记录来进行重新扫描

Compare

增量更新、原始快照方式,无论是对引用关系的插入还是删除,它们的记录操作都是通过写屏障技术来完成的

写屏障技术被用于记录对象的标记状态,写屏障技术一旦有引用关系发生了变化,它都会进行记录,但现有的 CMS、G1 都采用了插入式写屏障技术来进行优化,减少了一些性能上的开销工作

考虑性能的高低以及两者之间的权衡来决定以黑为根还是以灰为根来进行一次重新扫描工作

增量更新:会重新以黑色对象为根进行重新扫描(黑色—>白色),会浪费多一些时间,但考虑到发生漏标问题的情况也不太常见,所以扫描这部分黑色对象自然也就不多
原始快照:可能会把原本要取消引用的对象(灰色—>白色)给错误的标记为存活状态了,从而会产生一些浮动垃圾,也就是前面所说到的多标问题,能够被忽略

总结

该篇博文主要介绍了 CMS、G1 在「并发标记」阶段共同使用到的一种算法:三色标记算法,简要说明了它的多标问题,重点介绍了在使用其算法时会发生的漏标问题,有两种方式可以用来解决这种问题:增量更新、原始快照,CMS 使用的是前者,G1 使用的后者,最后对这两种不同解决方案方式作了一下对比,希望此博文你能够喜欢!

参考文献:《深入理解 Java 虚拟机》周志明著

博文放在 JVM 专栏里,欢迎订阅,会持续更新!

如果觉得博文不错,关注我 vnjohn,后续会有更多实战、源码、架构干货分享!

推荐专栏:Spring、MySQL,订阅一波不再迷路

大家的「关注❤️ + 点赞👍 + 收藏⭐」就是我创作的最大动力!谢谢大家的支持,我们下文见!

相关文章:

标记垃圾,有三种色彩:四千长文带你深入了解三色标记算法

🔭 嗨,您好 👋 我是 vnjohn,在互联网企业担任 Java 开发,CSDN 优质创作者 📖 推荐专栏:Spring、MySQL、Nacos、Java,后续其他专栏会持续优化更新迭代 🌲文章所在专栏&…...

277/300 React+react-router-dom+Vite 二级页面刷新时,白屏问题解决

(一)方案 BrowserRouter 换为 HashRouter (二)代码 import routes from ./routes import {ReactElement, Suspense} from react import {createHashRouter, Navigate} from react-router-dom // 生成路由数据 const generateR…...

如何做线上监控

1、背景 软件的质量是需要全生命周期进行关注的,在生产环境下QA的活动就是测试右移,测试右移最关键的手段就是线上监控,也是至关重要的一个环节,可以通过技术的手段,提前感知到线上问题和风险,先于用户提前发现问题,提升服务可感知性,从而降低客户投诉。 2、通用原则…...

饥荒开服教程——游戏

饥荒开服教程——游戏 1. 开服环境2. 开服步骤2.1 创建集群2.2 安装服务端2.3 上传mod2.4 启动脚本2.5 上传地图2.6 设置访问令牌2.7 修改配置 3. 服务器命令3.1 关闭服务器3.2 回档 记录一些在饥荒联机版开服中遇到过的问题。 参考:3分钟创建你的饥荒联机专属服务…...

查询 npm/yarn 安装依赖的全局路径及路径修改

一、NPM 1.查询 npm 安装依赖的全局路径 npm prefix -g 2. 修改 npm 全局安装位置 npm config set prefix "D:\nodejs\node_modules\npm\node_modules" 3. 修改 npm 全局 cache 位置 npm config set cache "D:\nodejs\node_modules\npm\cache" 4. np…...

掌握Python的X篇_35_用Python为美女打码_图像库Pillow

本篇将会介绍python中的一个图像库Pillow。 文章目录 1. Pillow与PIL的关系2. 调整大小3. 加滤镜4. 剪裁5. 生成验证码 1. Pillow与PIL的关系 我们在网上搜python的图像库的话,可能搜到的时PIL。实际上之前python发展的时候就是PIL,这个库比较好用&…...

SpringBoot 异步、邮件任务

异步任务 创建一个Hello项目 创建一个类AsyncService 异步处理还是非常常用的,比如我们在网站上发送邮件,后台会去发送邮件,此时前台会造成响应不动,直到邮件发送完毕,响应才会成功,所以我们一般会采用多线…...

【LeetCode】45. 跳跃游戏 II - 贪婪算法

目录标题 2023-8-11 09:49:25 45. 跳跃游戏 II 2023-8-11 09:49:25 自己没做出来&#xff0c;废物Orz class Solution {public int jump(int[] nums) {int length nums.length;int end 0;int maxPosition 0;int steps 0;for (int i 0; i < length - 1; i) {maxPosit…...

[C初阶笔记]P1

什么是C语言 1、机器语言&#xff08;二进制&#xff09;>汇编语言&#xff08;助记符&#xff09;>高级语言&#xff08;C、C等&#xff09; 2、c语言擅长底层软件开发&#xff08;操作系统、驱动程序&#xff09;&#xff0c;并不意味着不能开发其他。 C语言更贴近操作…...

外企面试题

Interview Prepare is there anyone we can talk to for a character reference? yes, I have some teammate can help to provide related working information. why did you leave/quit your last job? I got blocked on my last job. I found I cant learn new things fr…...

【目标检测系列】YOLOV1解读

前言 从R-CNN到Fast-RCNN&#xff0c;之前的目标检测工作都是分成两阶段&#xff0c;先提供位置信息在进行目标分类&#xff0c;精度很高但无法满足实时检测的要求。 而YoLo将目标检测看作回归问题&#xff0c;输入为一张图片&#xff0c;输出为S*S*(5*BC)的三维向量。该向量…...

Sentieon | 每周文献-Multi-omics(多组学)-第九期

多组学系列文章-1 标题&#xff08;英文&#xff09;&#xff1a; Prediction of axillary lymph node metastasis in triple-negative breast cancer by multi-omics analysis and an integrated model标题&#xff08;中文&#xff09;&#xff1a; 基于多组学分析和综合模型…...

CSDN竞赛70期

CSDN竞赛70期 CSDN竞赛70期1.小张的手速大比拼分析代码 2.坐公交分析代码 3.三而竭分析代码 4.争风吃醋的豚鼠分析代码 CSDN竞赛70期 1.小张的手速大比拼 在很久很久以前&#xff0c;小张找到了一颗有 N 个节点的有根树 T 。 树上的节点编号在 1 到 N 范围内。 他很快发现树上…...

mac安装vscode 配置git

1、安装vscode 官网地址 下载mac稳定版安装很慢的解决办法 (转自) mac电脑如何解决下载vscode慢的问题 选择谷歌浏览器右上角的3个点&#xff0c;选择下载内容&#xff0c;右键选择复制链接地址&#xff0c;在新窗口粘贴地址&#xff0c; 把地址中的一段替换成下面的vscode.cd…...

UI自动化环境的搭建(python+pycharm+selenium+chrome)

最近在做一些UI自动化的项目&#xff0c;为此从环境搭建来从0到1&#xff0c;希望能够帮助到你&#xff0c;同时也是自我的梳理。将按照如下进行开展&#xff1a; 1、python的下载、安装&#xff0c;python环境变量的配置。 2、pycharm开发工具的下载安装。 3、selenium的安装。…...

AbstractQueuedSynchronizer

目录 AQS是什么AQS什么样内部类成员变量方法public如果不使用AQS会怎样 AQS的应用ReentrantLockSyncNonfairSyncFairSync 其他实现 AQS是什么 AbstractQueuedSynchronizer&#xff08;AQS&#xff09;是Java中的一个并发工具&#xff0c;位于java.util.concurrent.locks包中&a…...

谈谈什么是云计算?以及它的应用

作者&#xff1a;Insist-- 个人主页&#xff1a;insist--个人主页 作者会持续更新网络知识和python基础知识&#xff0c;期待你的关注 目录 ​编辑 一、什么是云计算 二、云计算的优势与劣势&#xff1f; 1、云计算的优势 ①提高资源利用率 ②提升效率 ③降低成本 2、云…...

【BASH】回顾与知识点梳理(十六)

【BASH】回顾与知识点梳理 十六 十六. 十二至十五章知识点总结及练习16.1 总结16.2 练习16.3 简答题 该系列目录 --> 【BASH】回顾与知识点梳理&#xff08;目录&#xff09; 十六. 十二至十五章知识点总结及练习 16.1 总结 绝对路径&#xff1a;『一定由根目录 / 写起』…...

docsify gitee 搭建个人博客

docsify & gitee 搭建个人博客 文章目录 docsify & gitee 搭建个人博客1.npm 安装1.1 在Windows上安装npm&#xff1a;1.2 在macOS上安装npm&#xff1a;1.3 linux 安装npm 2. docsify2.1 安装docsify2.2 自定义配置2.2.1 通过修改index.html&#xff0c;定制化开发页面…...

SpringBoot2-Tomcat部署

1.排除内置 Tomcat 在pom.xml文件中的下添加以下代码&#xff0c;用于排除SpringBoot内置Tomcat <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><exclusions><exclusion&…...

Linux链表操作全解析

Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表&#xff1f;1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...

YSYX学习记录(八)

C语言&#xff0c;练习0&#xff1a; 先创建一个文件夹&#xff0c;我用的是物理机&#xff1a; 安装build-essential 练习1&#xff1a; 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件&#xff0c;随机修改或删除一部分&#xff0c;之后…...

实现弹窗随键盘上移居中

实现弹窗随键盘上移的核心思路 在Android中&#xff0c;可以通过监听键盘的显示和隐藏事件&#xff0c;动态调整弹窗的位置。关键点在于获取键盘高度&#xff0c;并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...

全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比

目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec&#xff1f; IPsec VPN 5.1 IPsec传输模式&#xff08;Transport Mode&#xff09; 5.2 IPsec隧道模式&#xff08;Tunne…...

【开发技术】.Net使用FFmpeg视频特定帧上绘制内容

目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法&#xff0c;当前调用一个医疗行业的AI识别算法后返回…...

Rapidio门铃消息FIFO溢出机制

关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系&#xff0c;以下是深入解析&#xff1a; 门铃FIFO溢出的本质 在RapidIO系统中&#xff0c;门铃消息FIFO是硬件控制器内部的缓冲区&#xff0c;用于临时存储接收到的门铃消息&#xff08;Doorbell Message&#xff09;。…...

USB Over IP专用硬件的5个特点

USB over IP技术通过将USB协议数据封装在标准TCP/IP网络数据包中&#xff0c;从根本上改变了USB连接。这允许客户端通过局域网或广域网远程访问和控制物理连接到服务器的USB设备&#xff08;如专用硬件设备&#xff09;&#xff0c;从而消除了直接物理连接的需要。USB over IP的…...

群晖NAS如何在虚拟机创建飞牛NAS

套件中心下载安装Virtual Machine Manager 创建虚拟机 配置虚拟机 飞牛官网下载 https://iso.liveupdate.fnnas.com/x86_64/trim/fnos-0.9.2-863.iso 群晖NAS如何在虚拟机创建飞牛NAS - 个人信息分享...

永磁同步电机无速度算法--基于卡尔曼滤波器的滑模观测器

一、原理介绍 传统滑模观测器采用如下结构&#xff1a; 传统SMO中LPF会带来相位延迟和幅值衰减&#xff0c;并且需要额外的相位补偿。 采用扩展卡尔曼滤波器代替常用低通滤波器(LPF)&#xff0c;可以去除高次谐波&#xff0c;并且不用相位补偿就可以获得一个误差较小的转子位…...

Spring Security 认证流程——补充

一、认证流程概述 Spring Security 的认证流程基于 过滤器链&#xff08;Filter Chain&#xff09;&#xff0c;核心组件包括 UsernamePasswordAuthenticationFilter、AuthenticationManager、UserDetailsService 等。整个流程可分为以下步骤&#xff1a; 用户提交登录请求拦…...