Excel不相邻列如何打印在一起-英雄云拓展知识分享
151
2023-11-07
【摘要】 本书摘自《深入理解 Java 虚拟机 JVM 高级特性与最佳实践(第3版)》一书中第3章,第4节,周志明著。
3.4 HotSpot 的算法细节实现
3.2、3.3节从理论原理上介绍了常见的对象存活判定算法和垃圾收集算法,Java 虚拟 机实现这些算法时,必须对算法的执行效率有严格的考量,才能保证虚拟机高效运行。本章 设置这部分内容主要是为了稍后介绍各款垃圾收集器时做前置知识铺垫,如果读者对这部分 内容感到枯燥或者疑惑,不妨先跳过去,等后续遇到要使用它们的实际场景、实际问题时再 结合问题,重新翻阅和理解。
3.4.1 根节点枚举
我们以可达性分析算法中从GC Roots 集合找引用链这个操作作为介绍虚拟机高效实现 的第一个例子。固定可作为GC Roots的节点主要在全局性的引用(例如常量或类静态属性) 与执行上下文(例如栈帧中的本地变量表)中,尽管目标明确,但查找过程要做到高效并非 一件容易的事情,现在Java 应用越做越庞大,光是方法区的大小就常有数百上千兆,里面 的类、常量等更是恒河沙数,若要逐个检查以这里为起源的引用肯定得消耗不少时间。
迄今为止,所有收集器在根节点枚举这一步骤时都是必须暂停用户线程的,因此毫无 疑问根节点枚举与之前提及的整理内存碎片一样会面临相似的 “Stop The World” 的困扰。 现在可达性分析算法耗时最长的查找引用链的过程已经可以做到与用户线程一起并发(具体 见3.4.6节),但根节点枚举始终还是必须在一个能保障一致性的快照中才得以进行——这 里“一致性”的意思是整个枚举期间执行子系统看起来就像被冻结在某个时间点上,不会 出现分析过程中,根节点集合的对象引用关系还在不断变化的情况,若这点不能满足的话, 分析结果准确性也就无法保证。这是导致垃圾收集过程必须停顿所有用户线程的其中一个 重要原因,即使是号称停顿时间可控,或者(几乎)不会发生停顿的CMS 、G1 、ZGC 等收 集器,枚举根节点时也是必须要停顿的。
由于目前主流Java 虚拟机使用的都是准确式垃圾收集(这个概念在第1章介绍 Exact VM相对于Classic VM 的改进时介绍过),所以当用户线程停顿下来之后,其实并不需要一 个不漏地检查完所有执行上下文和全局的引用位置,虚拟机应当是有办法直接得到哪些地 方存放着对象引用的。在 HotSpot 的解决方案里,是使用一组称为 OopMap 的数据结构来 达到这个目的。 一旦类加载动作完成的时候,HotSpot 就会把对象内什么偏移量上是什么类 型的数据计算出来,在即时编译(见第11章)过程中,也会在特定的位置记录下栈里和寄 存器里哪些位置是引用。这样收集器在扫描时就可以直接得知这些信息了,并不需要真正一个不漏地从方法区等GC Roots 开始查找。
下面代码清单3-3是 HotSpot 虚拟机客户端模式下生成的一段String:hashCode() 方法 的本地代码,可以看到在0x026eb7a9处的 call 指令有 OopMap 记录,它指明了EBX 寄存 器和栈中偏移量为16的内存区域中各有一个普通对象指针 (Ordinary Object Pointer,OOP) 的引用,有效范围为从call 指令开始直到0x026eb730 (指令流的起始位置)+142 (OopMap 记录的偏移量)=0x026eb7be, 即 hlt 指令为止。
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们 18664393530@aliyun.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~