ad

《深入理解 Java 虚拟机 JVM 高级特性与最佳实践(第3版)》_求知之路漫漫_3.2.2 可达性分析算法

网友投稿 103 2023-11-07

【摘要】 本书摘自《深入理解 Java 虚拟机 JVM 高级特性与最佳实践(第3版)》一书中第3章,第2节,周志明著。

3.2.2 可达性分析算法

当前主流的商用程序语言 (Java 、C#, 上溯至前面提到的古老的Lisp) 的内存管理子 系统,都是通过可达性分析 (Reachability Analysis) 算法来判定对象是否存活的。这个算法 的基本思路就是通过一系列称为 “GC Roots” 的根对象作为起始节点集,从这些节点开始, 根据引用关系向下搜索,搜索过程所走过的路径称为“引用链”(Reference Chain),如果某 个对象到GC Roots间没有任何引用链相连,或者用图论的话来说就是从GC Roots到这个 对象不可达时,则证明此对象是不可能再被使用的。

《深入理解 Java 虚拟机 JVM 高级特性与最佳实践(第3版)》_求知之路漫漫_3.2.2 可达性分析算法

如图3- 1所示,对象object 5 、object 6 、object 7虽然互有关联,但是它们到 GC Roots 是不可达的,因此它们将会被判定为可回收的对象。在 Java 技术体系里面,固定可作为 GC Roots的对象包括以下几种:

口在虚拟机栈(栈帧中的本地变量表)中引用的对象,譬如各个线程被调用的方法堆 栈中使用到的参数、局部变量、临时变量等。

口在方法区中类静态属性引用的对象,譬如Java 类的引用类型静态变量。

口在方法区中常量引用的对象,譬如字符串常量池 (String Table) 里的引用。 口在本地方法栈中 JNI (即通常所说的Native 方法)引用的对象。

口 Java 虚拟机内部的引用,如基本数据类型对应的Class 对象, 一些常驻的异常对象 (比如 NullPointExcepiton 、OutOfMemoryError) 等,还有系统类加载器。

口所有被同步锁 (synchronized 关键字)持有的对象。

口 反 映Java 虚拟机内部情况的JMXBean 、JVMTI 中注册的回调、本地代码缓存等。

除了这些固定的GC Roots 集合以外,根据用户所选用的垃圾收集器以及当前回收的内 存区域不同,还可以有其他对象“临时性”地加入,共同构成完整GC Roots集合。譬如后 文将会提到的分代收集和局部回收 (Partial GC), 如果只针对Java 堆中某一块区域发起垃 圾收集时(如最典型的只针对新生代的垃圾收集),必须考虑到内存区域是虚拟机自己的实 现细节(在用户视角里任何内存区域都是不可见的),更不是孤立封闭的,所以某个区域里 的对象完全有可能被位于堆中其他区域的对象所引用,这时候就需要将这些关联区域的对 象也一并加入GC Roots 集合中去,才能保证可达性分析的正确性。

目前最新的几款垃圾收集器°无一例外都具备了局部回收的特征,为了避免GC Roots 包含过多对象而过度膨胀,它们在实现上也做出了各种优化处理。关于这些概念、优化技 巧以及各种不同收集器实现等内容,都将在本章后续内容中一一介绍。

3.2.3 再谈引用

无论是通过引用计数算法判断对象的引用数量,还是通过可达性分析算法判断对象是 否引用链可达,判定对象是否存活都和“引用”离不开关系。在JDK 1.2版之前, Java 里 面的引用是很传统的定义:如果reference 类型的数据中存储的数值代表的是另外一块内存 的起始地址,就称该 reference 数据是代表某块内存、某个对象的引用。这种定义并没有什 么不对,只是现在看来有些过于狭隘了, 一个对象在这种定义下只有“被引用”或者“未 被引用”两种状态,对于描述一些“食之无味,弃之可惜”的对象就显得无能为力。譬如 我们希望能描述一类对象:当内存空间还足够时,能保留在内存之中,如果内存空间在进 行垃圾收集后仍然非常紧张,那就可以抛弃这些对象——很多系统的缓存功能都符合这样 的应用场景。

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们 18664393530@aliyun.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:《Python+3自动化软件发布系统》Django 2实战_了解Python的更好方法_3.7 GitLab REST API
下一篇:《自己动手写 Python 虚拟机》_更理解虚拟机的意义_2.3 文法分析
相关文章

 发表评论

暂时没有评论,来抢沙发吧~

×