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

在这里插入图片描述

🔭 嗨,您好 👋 我是 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,订阅一波不再迷路

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ArcGIS Maps SDK for JavaScript系列之一:在Vue3中加载ArcGIS地图

目录 ArcGIS Maps SDK for JavaScript简介ArcGIS Maps SDK for JavaScript 4.x 的主要特点和功能AMD modules 和 ES modules两种方式比较Vue3中使用ArcGIS Maps SDK for JavaScript的步骤创建 Vue 3 项目安装 ArcGIS Maps SDK for JavaScript创建地图组件 ArcGIS Maps SDK for …

Java多线程知识点,看这一篇就够了!(超详细)

目录 一、认识线程(Thread) 1、概念 2、第一个多线程程序 (1)观察线程 3、创建线程 二、Thread 类及常见方法 1、Thread 的常见构造方法 2、Thread 的几个常见属性 3、启动一个线程:start 4、终止一个线程 &…

注意:阿里云服务器随机分配可用区说明

阿里云服务器如有ICP备案需求请勿选择随机可用区,因为当前地域下的可用区可能不支持备案,阿里云百科分享提醒大家,如果你的购买的云服务器搭建网站应用,网站域名需要使用这台云服务器备案的话,不要随机分配可用区&…

什么是响应式设计?列举几种实现响应式设计的方法。

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 什么是响应式设计?⭐ 实现响应式设计的方法⭐ 写在最后 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅!这个专栏…

Android OkHttp源码分析--分发器

OkHttp是当下Android使用最频繁的网络请求框架,由Square公司开源。Google在Android4.4以后开始将源码中 的HttpURLConnection底层实现替换为OKHttp,同时现在流行的Retrofit框架底层同样是使用OKHttp的。 OKHttp优点: 1、支持Http1、Http2、Quic以及Web…

使用shift关键字,写一个带二级命令的脚本(如:docker run -a -b -c中的run)

省流:shift关键字 探索思路 最近有一个小小的需求,写一个类似于docker run -a -b -c这样的脚本,这个脚本名为doline,它本身可以执行(doline -a -b -c),同时又带有几个如run、init、start这样的…

【VSCode】查看二进制文件

1.安装插件Hex Editor 2.打开二进制文件 3.执行Hex Editor命令

基于.Net开发的ChatGPT客户端,兼容Windows、IOS、安卓、MacOS、Linux

2023年目前要说最热的点,肯定是ChatGPT了。 ChatGPT官方提供的网页版本,还有需要科*上网,很多人都会基于此进行封装。 现在是移动互联网时代,基于手机APP的需求还是很大的。 所以,今天给大家推荐一个ChatGPT客户端开…

YOLOv5入门实践(2)— 手把手教你使用make sense标注数据集(附工具地址+使用教程)

前言:Hello大家好,我是小哥谈。鉴于labelimg图像标注软件安装起来比较麻烦,本节课再给大家介绍另外一款数据集标注工具。这是一款在线标注数据集的工具,用起来非常的方便。🌈 前期回顾: YOLOv5入门实践&…

【深度学习MOT】SMILEtrack SiMIlarity LEarning for Multiple Object Tracking,论文

论文:https://arxiv.org/abs/2211.08824 文章目录 AbstractIntroduction2. 相关工作2.1 基于检测的跟踪2.1.1 检测方法2.1.2 数据关联方法 2.2 基于注意力的跟踪 3. 方法3.1 架构概述3.2 用于重新识别的相似性学习模块(SLM) Experimental Res…

Mysql数据库第十三课-----------sql语句的拔高3--------直冲云霄

作者前言 🎂 ✨✨✨✨✨✨🍧🍧🍧🍧🍧🍧🍧🎂 ​🎂 作者介绍: 🎂🎂 🎂 🎉🎉&#x1f389…

【MySQL--->数据库基础】

文章目录 [TOC](文章目录) 一、基本概念二、实际应用中的数据库三、mysql的架构四、mysql语句分类五、存储引擎查看 一、基本概念 mysql本质是一个CS模式的网络服务,mysql是客户端,mysqld是服务端,提供高效的数据存取方案.数据库系统简单来说是一个数据集合加上管理这个数据集…

Git介绍及常用命令详解

一、Git的概述 Git是一个分布式版本控制工具,通常用来对软件开发过程中的源代码文件进行管理。 Git 会跟踪我们对文件所做的更改,因此我们可以记录已完成的工作,并且可以在需要时恢复到特定或以前的版本。Git 还使多人协作变得更加容易&…

网络安全的相关知识点

网络安全威胁类型: 1.窃听:广播式网络系统。 2.假冒 3.重放:重复一份报文或者报文的一部分,以便产生一个被授权的效果。 4.流量分析 5.数据完整性破坏 6.拒绝服务 7.资源的非授权使用 8.陷门和特洛伊木马:木马病毒有客…

Telerik UI for ASP.NET Core Crack

Telerik UI for ASP.NET Core Crack Telerik ASP.NET Core还包括MVC和Kendo UI捆绑包(用于JavaScript)、Figma的设计工具包以及文档处理库、用于ASP.NET Core的Telerik REPL、RTL支持、辅助功能和键盘导航、主题化、虚拟课堂培训、详细文档、演示、KBs和世界级支持。使用一整套…

Ubuntu 20.04 APT 方式安装 mysql 5.7

Ubuntu 20.04 直接 apt 安装的 mysql 是 8.0 ,现在需要安装 5.7 版本,还颇费周章!按照文档直接点进去那个 MySQL APT Repository 中(https://dev.mysql.com/downloads/repo/apt/)只显示了 8.0 ,没有其他版本…

RHEL 7配置HAProxy实现Web负载均衡

一、测试环境HAProxy: 主机名:RH7-HAProxy IP地址:192.168.10.20 操作系统:Red Hat Enterprise Linux Server release 7.2 (Maipo)最小化安装 防火墙与SELinux:关闭 安装的服务:HAProxy-1.5.14 WEB01: 主…

SpringBoot3数据库集成

标签:Jdbc.Druid.Mybatis.Plus; 一、简介 项目工程中,集成数据库实现对数据的增晒改查管理,是最基础的能力,而对于这个功能的实现,其组件选型也非常丰富; 通过如下几个组件来实现数据库的整合…

微信小程序 map地图(轨迹)

allMarkers效果图 废话少说直接上马(最后是我遇到的问题) cover-view是气泡弹窗,可以自定义弹窗,要配合js:customCallout,如果是非自定义的话:callout(可以修改颜色、边框宽度、圆角…

【设计模式】拦截过滤器模式

拦截过滤器模式(Intercepting Filter Pattern)用于对应用程序的请求或响应做一些预处理/后处理。定义过滤器,并在把请求传给实际目标应用程序之前应用在请求上。过滤器可以做认证/授权/记录日志,或者跟踪请求,然后把请…