JVM18_CMS低延迟垃圾收集器、概述、原理、优缺点、参数设置、三色标记、ASTB 和 Incremental Update、记忆集与卡表(三)

简介: ⑥. 原始快照SATB 和 增量更新Incremental Update⑦. 记忆集与卡表

⑥. 原始快照SATB 和 增量更新Incremental Update


①. 增量更新(Incremental Update):在并发标记过程中,把赋值的这种新增的引用,做一个集合存起来。 在重新标记的时候会找到集合里面的引用然后重新去扫描,再把源头标记为灰色。这就是我们的增量更新


(如下图中的D如果是白色对象没有引用,某一个时刻由于用户线程的影响,将A黑色对象引用了D的情况,解决办法:使用写屏障(这个写屏障在之后)和增量更新解决)


微信图片_20220108144135.png


②. 在把我们新增的引用放到集合的时候,会实现一种写屏障的方式。在对象前后通过一个dirty card queue将引用信息, 存在card中,这个dirty card queue会放在cardtable中,而cardtable是记忆集的具体实现,最终这个引用就会放在记忆集中的


(写屏障我们可以理解为在赋值操作的前面加一个方法,赋值的后面做一些操作,也可以理解为AOP。具体的C++实现代码如下图:)


微信图片_20220108144153.png


③. 原始快照(SATB)算法认为开始标记的都认为是活的对象,如上下图所示,引用B到D的引用改为B到C时,通过write barrier写屏障技术,会把B到D的引用推到gc遍历执行的堆栈上,保证还可以遍历到D对象,相对于d来说,引用从B–>A,SATB 是从源入手解决的,即上面说的第2种情况,


这也能理解为啥叫satb了,即认为开始时所有能遍历到的对象都是需要标记的,即都认为是活的。如果我把b = null,那么d就是垃圾了, satb算法也还是会把D最终标记为黑色,导致D在本轮gc不能回收,成了浮动垃圾


(自己的理解:如上图中的B灰色对象某一个时刻由于用户线程的影响将B到D的引用置为null,解决办法:使用原始快照和写屏障 注意:这个写屏障在前面)


微信图片_20220108144211.png


微信图片_20220108144227.png


⑦. 记忆集与卡表


①. 在刚刚我们再说写屏障的时候提到了卡表,那么我们现在就来说说卡表是干什么用的。但是在说记忆集与卡表之前,我们要先知道what is 跨带引用~


②. 跨带引用:


所谓跨带引用就是老年代的对象引用了新生代的对象,或者新生代的对象引用了老年代的对象。那对于这种情况我们的GC在进行扫描的时候不可能直接把我们的整个堆都扫描完,那这样效率也太低了。所以这时候就需要开辟了一小块空间,维护这种引用,而不必让GC扫描整个堆区域。


③. 记忆集(在新生代中)


记忆集也叫rememberSet,垃圾收集器在新生代中建立了记忆集这样的数据结构,用来避免把整个老年代加入到GC ROOTS的扫描范围中。对于记忆集来说,我们可以理解为他是一个抽象类,那么具体实现它的方法将由子类去完成。这里我们简单列举一下实现记忆集的三种方式:


1.字长精度


2.对象精度


3.卡精度(卡表)


④. 卡表(在老年代中)


卡表(Card Table)是一种对记忆集的具体实现。主要定义了记忆集的记录精度、与堆内存的映射关系等。卡表中的每一个元素都对应着一块特定大小的内存块,这个内存块我们称之为卡页(card page),当存在跨带引用的时候,它会将卡页标记为dirty。那么JVM对于卡页的维护也是通过写屏障的方式,这也就是为什么刚刚我们跟进写屏障操作到最后会发现它会对卡表进行一系列的操作。


注意:(1). 卡表是使用一个字节数组实现:CARD_TABLE[ ],每个元素对应着其标识的内存区域一块特定大小的内存块,称为"卡页"。hotSpot使用的卡页是2^9大小,即512字节


(2). 一个卡页中可包含多个对象,只要有一个对象的字段存在跨代指针,其对应的卡表的元素标识就变成1,表示该元素变脏,否则为0。GC时,只要筛选本收集区的卡表中变脏的元素加入GCRoots里。


相关文章
|
23天前
|
缓存 Prometheus 监控
Elasticsearch集群JVM调优设置合适的堆内存大小
Elasticsearch集群JVM调优设置合适的堆内存大小
192 1
|
22天前
|
存储 监控 Java
合理设置JVM堆大小
合理设置JVM堆大小
27 4
|
2月前
|
存储 监控 算法
美团面试:说说 G1垃圾回收 底层原理?说说你 JVM 调优的过程 ?
尼恩提示: G1垃圾回收 原理非常重要, 是面试的重点, 大家一定要好好掌握
美团面试:说说 G1垃圾回收 底层原理?说说你 JVM 调优的过程  ?
|
2月前
|
存储 监控 算法
JVM调优深度剖析:内存模型、垃圾收集、工具与实战
【10月更文挑战第9天】在Java开发领域,Java虚拟机(JVM)的性能调优是构建高性能、高并发系统不可或缺的一部分。作为一名资深架构师,深入理解JVM的内存模型、垃圾收集机制、调优工具及其实现原理,对于提升系统的整体性能和稳定性至关重要。本文将深入探讨这些内容,并提供针对单机几十万并发系统的JVM调优策略和Java代码示例。
57 2
|
2月前
|
前端开发 Java 应用服务中间件
JVM进阶调优系列(1)类加载器原理一文讲透
本文详细介绍了JVM类加载机制。首先解释了类加载器的概念及其工作原理,接着阐述了四种类型的类加载器:启动类加载器、扩展类加载器、应用类加载器及用户自定义类加载器。文中重点讲解了双亲委派机制,包括其优点和缺点,并探讨了打破这一机制的方法。最后,通过Tomcat的实际应用示例,展示了如何通过自定义类加载器打破双亲委派机制,实现应用间的隔离。
|
4月前
|
存储 算法 Java
JVM组成结构详解:类加载、运行时数据区、执行引擎与垃圾收集器的协同工作
【8月更文挑战第25天】Java虚拟机(JVM)是Java平台的核心,它使Java程序能在任何支持JVM的平台上运行。JVM包含复杂的结构,如类加载子系统、运行时数据区、执行引擎、本地库接口和垃圾收集器。例如,当运行含有第三方库的程序时,类加载子系统会加载必要的.class文件;运行时数据区管理程序数据,如对象实例存储在堆中;执行引擎执行字节码;本地库接口允许Java调用本地应用程序;垃圾收集器则负责清理不再使用的对象,防止内存泄漏。这些组件协同工作,确保了Java程序的高效运行。
32 3
|
4月前
|
C# UED 开发者
WPF打印功能实现秘籍:从页面到纸张,带你玩转WPF打印技术大揭秘!
【8月更文挑战第31天】在WPF应用开发中,打印功能至关重要,不仅能提升用户体验,还增强了应用的实用性。本文介绍WPF打印的基础概念与实现方法,涵盖页面元素打印、打印机设置及打印预览。通过具体案例,展示了如何利用`PrintDialog`和`PrintDocument`控件添加打印支持,并使用`PrinterSettings`类进行配置,最后通过`PrintPreviewWindow`实现打印预览功能。
446 0
|
4月前
|
C# UED 开发者
WPF动画大揭秘:掌握动画技巧,让你的界面动起来,告别枯燥与乏味!
【8月更文挑战第31天】在WPF应用开发中,动画能显著提升用户体验,使其更加生动有趣。本文将介绍WPF动画的基础知识和实现方法,包括平移、缩放、旋转等常见类型,并通过示例代码展示如何使用`DoubleAnimation`创建平移动画。此外,还将介绍动画触发器的使用,帮助开发者更好地控制动画效果,提升应用的吸引力。
221 0
|
2月前
|
存储 安全 Java
jvm 锁的 膨胀过程?锁内存怎么变化的
【10月更文挑战第3天】在Java虚拟机(JVM)中,`synchronized`关键字用于实现同步,确保多个线程在访问共享资源时的一致性和线程安全。JVM对`synchronized`进行了优化,以适应不同的竞争场景,这种优化主要体现在锁的膨胀过程,即从偏向锁到轻量级锁,再到重量级锁的转变。下面我们将详细介绍这一过程以及锁在内存中的变化。
40 4
|
13天前
|
存储 监控 算法
深入探索Java虚拟机(JVM)的内存管理机制
本文旨在为读者提供对Java虚拟机(JVM)内存管理机制的深入理解。通过详细解析JVM的内存结构、垃圾回收算法以及性能优化策略,本文不仅揭示了Java程序高效运行背后的原理,还为开发者提供了优化应用程序性能的实用技巧。不同于常规摘要仅概述文章大意,本文摘要将简要介绍JVM内存管理的关键点,为读者提供一个清晰的学习路线图。