当前位置: 首页 > 知识库问答 >
问题:

关于《深入理解java虚拟机》阅读时候的问题?

施利
2024-03-11

第一个问题是关于三色标记的问题。
jvm 的 原始快照,如果一个黑色对象关联到一个新的白色对象。这个对象并不是从灰色对象逃脱的。不是也一样会产生对象消失吗?为什么说必须满足两个条件才会出现对象消失的问题。这样一样会导致不该被回收的标记为白色。

第二个是关于卡表和记忆集的问题。
卡表中变脏的卡页会加入GC Root ,是将整个卡页的对象加入GC Root 还是通过某种方式,筛选出卡页中有跨代引用的对象加入GC Root, 如果还要筛选,依据是什么呢?如果不筛选,这样是否会产生浮动垃圾?

第三个是关于写屏障解决伪共享的问题,为什么多一个判断就能解决伪共享的问题?

共有1个答案

蓟清野
2024-03-11

1.首先请了解一个概念:在Java虚拟机(JVM)中,垃圾收集器在工作时会将对象分为三种颜色:白色、灰色和黑色。白色对象是可能被回收的垃圾,灰色对象是正在被检查是否有引用其他对象的中间状态,黑暗物体关联到一个新创建或者已经存在但未标记(即仍然是白领) 的那些已经变成了灰暗或者黑暗领涂成灰涂料。
现在假设有这样一种情况:一个已经检查过(也就是说它现在是黑暗物体关联到一个新创建或者已经存在但未标记(即仍然是白领) 的那些已经变成了灰暗或者黑暗领涂成灰涂料。如果此时它突然引用了一个新创建的、还没来得及检查 的那些尚未被访问过 ,也就说这个新 对象还处于“可能回收”的状态。如果垃圾收集器没有注意到这一点,并且继续按照原计划进行工作,则可能会错误地将这个 新对象当做无人引用而进行回收。为了防止出现上述情况,在JVM中有一种叫做“写屏障”的技术。这个技术的作用就是在一个黑暗物体关联到一个新创建或者已经存在但未标记(即仍然是白领) 的那些已经变成了灰暗或者黑暗领涂成灰涂料时,立即将这个黑色对象重新标记为“正在检查”的状态,也就是说将它重新染成灰色。这样一来,在接下来的检查过程中,垃圾收集器就能再次检查到 这个 对象,并且发现它现在其实还有被引用。
所以说,“必须满足两个条件才会出现消失”:第一,有一个黑色对象突然引用了新创建的白色对象;第二,“写屏障”没有正确地工作。只有当这两点同时满足时,才可能出现不该被回收的 对象 被错误地回收。
但实际上,在JVM运行过程中,“写屏障”通常都能正确工作,并防止上述情况发生。
2.卡表和记忆集都是用于优化跨代引用查找以提高GC效率而设计出来 的数据结构。当卡页变脏时,意味着这个卡页可能包含了跨代引用。在GC过程中,我们需要将这个卡页加入到GC Root中。但是,并不是将整个卡页的所有对象都加入到GC Root,而是需要进行一次扫描来找出那些真正包含跨代引用的对象,并将它们加入到GC Root。如果不进行筛选而直接把整个卡页都当作Roots来处理,那么会导致浮动垃圾(Floating Garbage),也就是实际上可以回收但在当前的垃圾收集过程中没有被回收的对象。
3.共享(False Sharing)问题通常出现在多线程环境下,当多线程尝试修改同一缓存行上不同数据时会导致性能下降。写屏障可以帮助解决伪共享问题因为它提供了一种机制来控制并发修改内存数据:通过写屏障我们可以确保某些写操作按照预期顺序执行并且对其他线程可见。具体如何解决取决于具体实现和使用场景。
例如,在JVM GC实现如G1或CMS等使用了写屏障技术,在新生代复制阶段或者并发标记阶段等,写屏障可以确保对象的引用更新对GC线程可见,从而避免了可能的并发问题。但这并不直接解决伪共享问题。伪共享问题通常需要通过其他方式解决,例如缓存行填充(Cache Line Padding)或者使用支持缓存行对齐的数据结构等。

针对你提出的问题,我作答如下:
你的理解是正确的。写屏障确实可以看作是一种AOP技术,它在运行时插入一些额外的操作来帮助垃圾收集器追踪对象引用关系的变化。对于你提到G1垃圾收集器使用原始快照技术和写屏障如何解决对象消失问题,这里需要明确一点:在并发标记阶段开始时,所有活动对象都被认为是灰色的。这意味着如果一个白色对象在并发标记阶段关联到一个已经检查过(即黑色)的对象上,并且没有其他灰色或黑色引用指向它,则该白色对象不会消失。原因如下:由于G1使用了SATB技术,在并发标记开始时会记录下所有活动(即可达) 对象。如果某个时间点有一个新创建或者从灰变为白(断开了与其他已经检查过得黑/灰节点联系) 的节点被某个已经检查过得黑节点所引用,则此刻写屏障就会起作用,并将该新创建或者从灰变为白 的节点重新视为"可达"状态(即重新视其为"活动")。所以,在G1中,写屏障主要用于处理并发标记阶段,对象引用关系的变化。当一个黑色对象引用一个白色对象时(即断开了原有的灰色或黑色引用),写屏障会将这个白色对象重新标记为灰色,并将其放入到待处理队列中。这样就保证了在并发标记阶段,不会有活动的(即可达的)白节点被遗漏。我总结一下:在G1垃圾收集器中,使用原始快照技术和写屏障可以确保在并发标记阶段不会遗漏任何活动节点。当出现黑节点新关联到一个新创建或者从灰变为白 的节点时(断开了与其他已经检查过得黑/灰节点联系),此刻写屏障就起作用,并将该新创建或者从灰变为白 的节点重新视其为"活动"状态(即重新视其为"可达")。

 类似资料:
  • 本 repo 为《深入理解 Java 虚拟机 第2版》的阅读笔记,并对全书内容按照自己的理解进行了一定程度的整理。

  • Java 虚拟机屏蔽了与具体操作系统平台相关的信息,使得 Java 语言编译程序只需生成在 Java 虚拟机上运行的目标代码,就可以在多种平台上不加修改地运行。

  • 本文向大家介绍深入理解java虚拟机的故障处理工具,包括了深入理解java虚拟机的故障处理工具的使用技巧和注意事项,需要的朋友参考一下 前言 本文主要给大家介绍的是java虚拟机的故障处理工具,文中提到这些工具包括: 名称 主要作用 jps JVM process Status Tool, 显示指定系统内所有的HotSpot虚拟机进程。通常是本地主机 jstat JVM Statistics Mo

  • 本文向大家介绍深入浅析Nginx虚拟主机,包括了深入浅析Nginx虚拟主机的使用技巧和注意事项,需要的朋友参考一下 一 虚拟主机 1.1 虚拟主机概念  对于Nginx而言,每一个虚拟主机相当于一个在同一台服务器中却相互独立的站点,从而实现一台主机对外提供多个 web 服务,每个虚拟主机之间是独立的,互不影响的。 1.2 虚拟主机类型  通过 Nginx 可以实现虚拟主机的配置,Nginx 支持三

  • 本文向大家介绍关于Java中HashCode方法的深入理解,包括了关于Java中HashCode方法的深入理解的使用技巧和注意事项,需要的朋友参考一下 1、0前言 最近在学习 Go 语言,Go 语言中有指针对象,一个指针变量指向了一个值的内存地址。学习过 C 语言的猿友应该都知道指针的概念。Go 语言语法与 C 相近,可以说是类 C 的编程语言,所以 Go 语言中有指针也是很正常的。我们可以通过将

  • 虚拟主机部分的代码在Apache 1.3中进行了完全的重写。本文档试图详细解释Apache在接受到请求后如何确定使用哪一个虚拟主机进行伺服。在新的NameVirtualHost指令的帮助下,虚拟主机的配置比1.3版以前更加简单和安全。 如果您只是想让它能够工作而不愿意进行深入理解,这里有一些示例。 解析配置文件 在<VirtualHost>配置段外有一个主服务器(main_server)段中包含着