三色标记法

可达性分析之三色标记算法详解 二、三色标记 在前文中提到了,在CMS的并发清理阶段才产生的垃圾,会被当做浮动垃圾,会留到下一次GC再清理。其实在并发标记阶段,由于用户线程在并发运行,也就可能导致引用关系改变,导致标记结果不准确,从而引发更加严重的问题,这些发生变更的数据会在重新标记阶段被处理,那么会出现什么问题?又是如何处理的呢? CMS算法的基础是通过可达性分析找到存活的对象,然后给存活的对象打个标记,最终在清理的时候,如果一个对象没有任何标记,就表示这个对象不可达,需要被清理。 并发标记阶段是从GC Root直接关联的对象开始枚举的 阅读详情

  垃圾回收算法包括:标记-清除、标记-复制、标记-整理。在此基础上可以增加分代(新生代/老年代),每代采取不同的回收算法,以提高整体的分配和回收效率。无论使用哪种算法,标记总是必要的一步。垃圾回收器的工作流程大体如下:

  1. 标记出哪些对象是存活的,哪些是垃圾(可回收)
  2. 进行回收(清除/复制/整理),如果有移动过对象(复制/整理),还需要更新引用

三色标记法

基本算法
要找出存活对象,根据可达性分析,从GC Roots开始进行遍历访问,可达的则为存活对象。将遍历对象图过程中遇到的对象,按“是否访问过”这个条件标记成以下三种颜色:

  • 白色:尚未访问过
  • 黑色:本对象已访问过,而且本对象 引用到 的其他对象 也全部访问过了
  • 灰色:本对象已访问过,但是本对象 引用到 的其他对象 尚未全部访问完。全部访问后,会转换为黑色

假设现在有白、灰、黑三个集合(表示当前对象的颜色),其遍历访问过程为:
1、初始时,所有对象都在 【白色集合】中;
2、将GC Roots 直接引用到的对象 挪到 【灰色集合】中;
3、从灰色集合中获取对象:
  3.1. 将本对象 引用到的 其他对象 全部挪到 【灰色集合】中;
  3.2. 将本对象 挪到 【黑色集合】里面。
4、重复步骤3,直至【灰色集合】为空时结束。/5、结束后,仍在【白色集合】的对象即为GC Roots 不可达,可以进行回收。

注:如果标记结束后对象仍为白色,意味着已经“找不到”该对象在哪了,不可能会再被重新引用。

当Stop The World (STW)时,对象间的引用是不会发生变化的,可以轻松完成标记。而当需要支持并发标记时,即标记期间应用线程还在继续跑,对象间的引用可能发生变化,多标和漏标的情况就有可能发生。

多标-浮动垃圾
假设已经遍历到E(变为灰色了),此时应用执行了 objD.fieldE = null:
在这里插入图片描述
  D > E 的引用断开。此刻之后,对象E/F/G是“应该”被回收的。然而因为E已经变为灰色了,其仍会被当作存活对象继续遍历下去。最终的结果是:这部分对象仍会被标记为存活,即本轮GC不会回收这部分内存。
  这部分本应该回收 但是 没有回收到的内存,被称之为“浮动垃圾”。浮动垃圾并不会影响应用程序的正确性,只是需要等到下一轮垃圾回收中才被清除。
  另外,针对并发标记开始后的新对象,通常的做法是直接全部当成黑色,本轮不会进行清除。这部分对象期间可能会变为垃圾,这也算是浮动垃圾的一部分。

漏标-读写屏障
假设GC线程已经遍历到E(变为灰色了),此时应用线程先执行了:

var G = objE.fieldG; 
objE.fieldG = null;  // 灰色E 断开引用 白色G 
objD.fieldG = G;  // 黑色D 引用 白色G

在这里插入图片描述
  E > G 断开,D引用 G。此时切回GC线程继续跑,因为E已经没有对G的引用了,所以不会将G放到灰色集合;尽管因为D重新引用了G,但因为D已经是黑色了,不会再重新做遍历处理。
最终导致的结果是:G会一直停留在白色集合中,最后被当作垃圾进行清除。这直接影响到了应用程序的正确性,是不可接受的。
  不难分析,漏标只有同时满足以下两个条件时才会发生:
条件一:灰色对象 断开了 白色对象的引用;即灰色对象 原来成员变量的引用 发生了变化。
条件二:黑色对象 重新引用了 该白色对象;即黑色对象 成员变量增加了 新的引用。

从代码的角度看:

var G = objE.fieldG; // 1.读
objE.fieldG = null;  // 2.写
objD.fieldG = G;     // 3.写

1/读取 对象E的成员变量fieldG的引用值,即对象G;
2/对象E 往其成员变量fieldG,写入 null值。
3/对象D 往其成员变量fieldG,写入 对象G ;

  只要在上面这三步中的任意一步中进行修改,将对象G记录起来,然后作为灰色对象再进行遍历即可。比如放到一个特定的集合,等初始的GC Roots遍历完(并发标记),该集合的对象 遍历即可(重新标记)。
  重新标记是需要STW的,因为应用程序一直在跑的话,该集合可能会一直增加新的对象,导致永远都跑不完。当然,并发标记期间也可以将该集合中的大部分先跑了,从而缩短重新标记STW的时间,这个是优化问题了。
  写屏障用于拦截第二和第三步;而读屏障则是拦截第一步。它们的拦截的目的很简单:就是在读写前后,将对象G给记录下来。

写屏障(Store Barrier)
所谓的写屏障,其实就是指在赋值操作前后,加入一些处理:
(1) 写屏障 + SATB
  当对象E的成员变量的引用发生变化时(objE.fieldG = null;),可以利用写屏障,将E原来成员变量的引用对象G记录下来:当原来成员变量的引用发生变化之前,记录下原来的引用对象。这种做法的思路是:尝试保留开始时的对象图,即原始快照(Snapshot At The Beginning,SATB),当某个时刻 的GC Roots确定后,当时的对象图就已经确定了。
  比如 当时 D是引用着G的,那后续的标记也应该是按照这个时刻的对象图走(D引用着G)。如果期间发生变化,则可以记录起来,保证标记依然按照原本的视图来。
  扫描所有GC Roots 这个操作(即初始标记)通常是需要STW的,否则有可能永远都扫不完,因为并发期间可能增加新的GC Roots。

SATB破坏了条件一:【灰色对象 断开了 白色对象的引用】,从而保证了不会漏标。

(2) 写屏障 + 增量更新
  当对象D的成员变量的引用发生变化时(objD.fieldG = G;),可以利用写屏障,将D新的成员变量引用对象G记录下来:当有新引用插入进来时,记录下新的引用对象。这种做法的思路是:不要求保留原始快照,而是针对新增的引用,将其记录下来等待遍历,即增量更新(Incremental Update)。增量更新破坏了条件二:【黑色对象 重新引用了 该白色对象】,从而保证了不会漏标。

读屏障(Load Barrier)
  读屏障是直接针对第一步:var G = objE.fieldG;,当读取成员变量时,一律记录下来:这种做法是保守的,但也是安全的。因为条件二中【黑色对象 重新引用了 该白色对象】,重新引用的前提是:得获取到该白色对象,此时已经读屏障就发挥作用了。

三色标记法与现代垃圾回收器
  可达性分析的垃圾回收器几乎都借鉴了三色标记的算法思想,尽管实现的方式不尽相同:比如白色/黑色集合一般都不会出现、灰色集合可以通过栈/队列/缓存日志等方式进行实现、遍历方式可以是广度/深度遍历等等。
  对于读写屏障,以Java HotSpot VM为例,其并发标记时对漏标的处理方案如下:

  • CMS:写屏障 + 增量更新
  • G1:写屏障 + SATB

CMS中使用的增量更新,在重新标记阶段,除了需要遍历 写屏障的记录,还需要重新扫描遍历GC Roots(当然标记过的无需再遍历了),这是由于CMS对于astore_x等指令不添加写屏障的原因。

「 JVM 」 图解三色标记算法(增量更新与原始快照的实现) 在说 JVM 的三色标记算法之前,我们先来说下 JVM 对于常见对象存活判定算法与垃圾收集算法。常见对象存活判定算法有引用计数算法和可达性分析算法。引用计数法会产生循环引用问题,JVM 默认是通过可达性分析算法来判断对象是否存活的。标记-清除、标记-复制、标记-整理算法以及在此基础上的分代收集算法(新生代/老年代),每代采取不同的回收算法,以提高整体的分配和回收效率。这些垃圾收集算法首先做的都是通过可达性分析算法。 阅读详情

相关推荐

三色标记法详解

三色标记法详解

m0_54258715的博客 981

三色标记法详细图解

前言: 了当前主流编程语言的垃圾收集器基本上都是依靠可达性分析算法来判定对象 是否存活的,可达性分析算法理论上要求全过程都基于一个能保障一致性的快照中才能够进行分析, 这意味着必须全程冻结用户线程的运行。 在根节点枚举这个步骤中,由于GC Roots相比 起整个Java堆中全部的对象毕竟还算是极少数,且在各种优化技巧(如OopMap)的加持下,它带来 的停顿已经是非常短暂且相对固定(不随堆容量而增长)的了。可从GC Roots再继续往下遍历对象 图,这一步骤的停顿时间就必定会与Java堆容量直接成正比.

m0_53611007的博客 5447

【JVM】三色标记法与读写屏障

关于垃圾回收算法,基本就是那么几种:标记-清除、标记-复制、标记-整理。在此基础上可以增加分代(新生代/老年代),每代采取不同的回收算法,以提高整体的分配和回收效率。无论使用哪种算法,标记总是必要的一步。这是理算当然的,你不先找到垃圾,怎么进行回收?标记出哪些对象是存活的,哪些是垃圾(可回收);进行回收(清除/复制/整理),如果有移动过对象(复制/整理),还需要更新引用。本文着重来看下标记的部分。

九师兄 7113

三色标记算法过程及原理(Tri-color marking)

三色标记算法过程及原理

oJieSi的专栏 9202

SoapUI 5.0 模拟WebService接口实战:从WSDL文件到Mock服务端完整流程

本文详细介绍了如何使用SoapUI 5.0模拟WebService接口,从解析WSDL文件到搭建完整的Mock服务端流程。通过实战案例和效率技巧,帮助开发者快速掌握接口模拟技术,提升开发与测试效率。

weixin_26833139的博客 407

飞塔防火墙CVE-2022-40684漏洞复现:手把手教你搭建靶场环境(附调试技巧)

本文详细指导如何搭建Fortinet飞塔防火墙CVE-2022-40684认证绕过漏洞的靶场环境,涵盖虚拟机部署、网络配置、调试模式开启及漏洞原理分析。通过手把手教程,读者可掌握漏洞复现与深度调试技巧,深入理解该认证绕过漏洞的利用与防御。

h6i7j8的博客 695

go垃圾回收机制(三色标记法)& 屏障机制

为了保证栈的速度,如果为栈上的对象增加插入屏障,会大幅度增加引用对象的性能,所以栈空间不触发插入屏障,堆空间会触发插入屏障,而在回收白色之前会重新遍历扫描一次栈空间,此时添加STW暂停来保护栈,防止外界干扰(有新的白色被黑色添加);在Go使用的混合写屏障中是不会对栈空间进行写屏障的,栈上的对象在一开始就全部标记为黑色,并且在GC过程中新创建的对象也是黑色的,可能错放但不错杀;删除屏障的不足:回收精度低,一个对象即使被删除了最后一个指向它的指针也依旧可以活过这一轮,在下一轮GC中被删除(宁可放过也不错删);

要好好学习 1121

Neo4j 智能供应链应用源代码简析

本文简析Neo4j智能供应链应用的源代码,让你也可以快速开发自己的供应链应用。

Neo4j 开发者博客 1680

[Golang] Golang GC(三色标记法)

一、GO 1.3之前的标记删除 1.第一步,暂停程序业务逻辑,找出不可达对象,和可达对象 2.第二部,开始标记,程序找出它所有的可达对象,并做上标记 3.标记完之后,开始清楚未标记对象 4,停止暂停,让程序继续跑。然后循环重复这个过程直到process程序生命周期结束 标记-清除方法的缺点 1.stw(stop the world)让程序暂停,程序出现卡顿 2.标记需要扫描整个heap(堆) 3.清除数据会产生heap碎片 4.并发时,导致先前未被标记的误删除 改进 1.缩小stw范围,将清除挪出来,先恢复

神隐寻觅的博客 4660

RK3588 EVB开发板原理图讲解【六】

该原理图展示了eMMC Flash与主控芯片之间的连接关系,以及相关的电源、信号线路和去耦电容等。

weixin_48721556的博客 1174

在unity urp项目中 通过图片创建材质(透明光晕)

unity中通过图片创造材质(urp管道)

m0_49721415的博客 1541

详细图解JVM三色标记法

JVM垃圾回收—三色标记

自律使我自由 3121

反向代理的隐形陷阱:为何你的HTTPS请求会降级为HTTP?

本文深入探讨了Nginx反向代理中HTTPS降级为HTTP的隐形陷阱及其安全风险,分析了五大降级诱因,包括协议信息丢失、重定向配置错误等,并提供了完整的防御性配置方案和实战指南,帮助开发者确保Web应用的安全性。

kotlin6android的博客 453

Go 三色标记法:一种高效的垃圾回收策略

三色标记法是一种用于垃圾回收的算法,它将对象分为三种颜色:白色、黑色和灰色。这种分类基于对象之间的引用关系,以确定哪些对象仍然被使用,哪些可以被回收。白色对象:尚未被垃圾回收器访问的对象。黑色对象:已经访问过,并且其所有子对象(即直接或间接引用的对象)也已经被访问过的对象。灰色对象:已经访问过,但其子对象尚未全部访问的对象。Go 语言的三色标记法是一种高效且实用的垃圾回收策略,它通过减少程序暂停时间来优化性能。作为开发者,了解并掌握这一机制的使用技巧,可以帮助你编写更高效、更稳定的 Go 应用程序。

专注于全栈开发领域 1291

常见机械臂模型不用找!Mujoco这儿都有!

高质量的模型集合,franka panda,so-arm100,ur之类的机械臂都有。常见机械臂模型不用找!Mujoco这儿都有!大概346M,网速不行的可以下载zip。

darcsdn 992

《C#零基础入门之百识百例》(七)算数运算符 -- 圆的面积

运算符是一种告诉编译器执行特定的数学或逻辑操作的符号。C# 有丰富的内置运算符,本文带你学习C# 中算数运算符。

陈言必行 -- Unity游戏开发领域优质博主 3614

JVM 的三色标记法

例如,假设对象E已经被标记为灰色(表示已经被访问过,但其引用的对象尚未全部访问),此时用户线程执行了objD.fieldE = null,断开了D对E的引用。但由于E已经被标记为灰色,它仍然会被当作存活对象继续遍历,最终E、F、G等对象都会被标记为黑色(表示存活),从而不会被回收。显然在可达性分析刚刚开始的阶段, 所有的对象都是白色的, 若在分析结束的阶段, 仍然是白色的对象, 即代表不可达。漏标问题是指原本应该被标记为存活的对象,却被错误地标记为垃圾对象,从而导致这些对象被错误地回收。

lgllinktheworld的博客 1150

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

Golang基础-GC三色标记法

三色标记法是垃圾回收算法中的一种高效的标记方式,它通过将对象分为白色、灰色、黑色来区分对象的状态,从而确保并发环境下的内存管理。Go 从1.5 版本开始采用三色标记法,并结合并发标记和清理,避免了传统 GC 的停止世界问题,使得 GC 停顿时间大大减少,应用程序性能得到了提升。不同的 Go 版本不断优化 GC 的并发性和效率,尤其是在Go 1.11和之后的版本,GC 变得更加高效和精细。

qq_38609643的博客 1591

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

深入理解 Golang GC 的三色标记法

三色标记法是 Golang 垃圾回收中使用的一种算法,用于追踪和标记活跃对象,从而确定哪些对象可以被回收。白色:表示尚未被标记的对象,即初始状态下所有对象都为白色。灰色:表示已经被发现,但还未被完全追踪的对象。黑色:表示对象及其引用已经被完全追踪,是确定的活跃对象,不会被回收。三色标记法作为 Golang 垃圾回收机制的重要组成部分,虽然在日常开发中可能不常直接接触,但它对于理解 Golang 的内存管理和性能优化具有重要意义。

m0_57836225的博客 1657

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

JVM:三色标记法详解

三色标记法是一种垃圾回收法,它可以让JVM不发生或仅短时间发生STW(Stop The World),从而达到清除JVM内存垃圾的目的。JVM中的所使用垃圾回收算法即为三色标记法。

2301_76166241的博客 2527

Golang三色标记法面试复习

垃圾回收是指对不再使用的内存资源进行自动回收的功能。C++等语言中使用的是手动管理,而Go中则是自动管理。Go的垃圾回收机制主要是三色标记法,可以减少因垃圾回收导致程序暂停的影响。本文主要是学习这个机制。

Ws_Te47的博客 1059

Golang GC 三色标记法

把图(可能死亡):未被回收器访问到的对象。在回收开始阶段,所有对象均为白色,当回收结束后,白色对象均不可达。(波面):已被回收器访问到的对象,但回收器需要对其中的一个或多个指针进行扫描,因为他们可能还指向白色对象。(确定存活):已被回收器访问到的对象,其中所有字段都已被扫描,黑色对象中任何一个指针都不可能直接指向白色对象。

王安的博客 2193

三色标记法与写屏障(WriteBarrier)

GC算法从整体思路上来讲基本只有两大流派,即引用计数派和扫描标记派。而扫描标记派又分为可并行方式和不可并行方式。三色标记法就是可并行方式最常用的一种扫描标记方法。网上对于三色标记法的详细介绍多如牛毛,本文重点不在这里,所以只简单介绍一下原理。本文其实没有重点。

zhiai315的博客 2427

CMS 三色标记法

为什么引入三色标记法 为了提供 JVM 垃圾回收的性能,从 CMS 垃圾收集器开始,引入了并发标记的概念(此处的并发标记是指与用户线程一起工作)。引入并发标记的过程就会带来一个问题,在业务执行的过程中,会对现有的引用关系链出现改变。具体如下图: 当 GC 线程开始标记对象的时候,如果这个时候用户线程修改了 F 和 A 的引用,因为此时 A对象已经被遍历完成了,GC线程就不会再对 A 有新的标记操作,这样 GC 线程就会认为 B,C,D 对象没有被任何对象引用,就会被当成垃圾回收。 很明显在并发的情况下,“

fuwei2020的博客 694

Go GC原理深度解析:三色标记法详解

三色标记法的核心思想是将内存中的对象按照访问状态分为三种颜色,然后通过颜色的转换来实现垃圾回收。这就像是在一个杂乱的仓库中整理物品 - 我们给物品贴上不同颜色的标签,逐步处理,最终清理掉不需要的物品。GC频率降低到平均每15秒一次CPU中用于GC的比例降至约8%99.9%请求延迟控制在30ms以内系统稳定处理100万QPS,无明显性能下降关键经验总结小优化积累成大改进:许多1%的优化累积起来,最终带来显著提升数据驱动优化:始终基于监控数据和分析结果指导优化方向理解GC原理带来实质改进。

sinat_27016095的博客 1094
上一篇: MySQL主从复制
下一篇: Token解析
K. Bob
博客等级 码龄8年 82粉丝 294原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值