商城首页欢迎来到中国正版软件门户

您的位置: 首页 > 文章列表 > 编程开发 > 可达性分析算法(Reachability Analysis):如何通过 GC Roots 判定一个对象是否已经“死亡”

可达性分析算法(Reachability Analysis):如何通过 GC Roots 判定一个对象是否已经“死亡”

  发布于2026-05-23 阅读(0)

扫一扫,手机访问

可达性分析算法:JVM如何判定对象“生死”

在Ja va的世界里,一个对象何时该被回收,并非由程序员说了算,也不是看它有没有被“遗忘”。虚拟机自有一套严谨的判定逻辑,这套逻辑的核心,就是可达性分析算法。简单来说,它不关心对象被引用了多少次,只关心一件事:这个对象,还能不能从一组“根”对象出发,被找到?

可达性分析算法(Reachability Analysis):如何通过 GC Roots 判定一个对象是否已经“死亡”

上图清晰地展示了这个过程:从一组确定的起点(GC Roots)出发,沿着对象间的引用关系(引用链)进行搜索。所有能被“触达”的对象,都被标记为存活;而那些孤悬在引用网络之外的、无法从任何根节点抵达的对象,就会被判定为“死亡”,成为待回收的垃圾。这就好比在一片森林里,从几个固定的地标出发,所有能通过小路连通到的区域都是“可达”的,而那些完全隔绝、无路可通的区域,自然就被划为了可清理的荒地。

哪些对象能当 GC Roots?

那么,什么样的对象有资格成为这片森林的“地标”——GC Roots呢?它们必须是JVM在运行时能明确识别、且在任何情况下都“绝对安全”、不会被回收的对象。通常包括以下几类:

  • 虚拟机栈中的引用:每个正在执行的方法,其栈帧的局部变量表里所引用的对象。比如你方法里定义的局部对象、传入的参数对象,只要线程还没结束,它们就是“根”。
  • 方法区中的静态引用:类被加载后,其静态属性(static字段)所引用的对象。这些属于类级别的数据,生命周期通常很长。
  • 方法区中的常量引用:常量池里引用的对象,典型的比如字符串常量(在常量池中),或者被声明为final static的包装类对象。
  • 本地方法栈中的JNI引用:当Ja va代码调用本地(Native)方法时,这些方法正在使用的Ja va对象也会被视作根,以确保本地代码能安全访问。

这些根对象构成了搜索的绝对起点,是判定存活对象的基石。

引用链是怎么形成的?

引用链,其实就是对象之间手拉手形成的可达路径。它并非必须是直接引用,而是可以逐级传递。

举个例子:假设对象A是GC Root,它引用了对象B,对象B又引用了对象C,而对象C最后引用了对象D。那么,尽管A和D之间隔了两层,但只要这条链上的每一个引用都是有效的(没有被置为null,也没有被其他引用覆盖),从A出发,D就是可达的,因此D也是存活对象。

关键在于链条的完整性。一旦中间某个环节断裂——比如将B的引用设置为null——那么从B往后的整个子图(包括C和D),即使它们之间还相互引用,也因为失去了与根节点的连接,变成了不可达的“孤岛”,从而被标记为可回收。

为什么引用计数法没被采用?

提到对象存活判定,很多人会想到更直观的引用计数法:每个对象带一个计数器,被引用一次就加一,引用失效就减一,归零即回收。听起来简单明了,对吧?

但这个方法有个致命的缺陷:它无法处理循环引用。想象一下,对象A和对象B互相引用,除此之外,再也没有任何外部引用指向它们。此时,A和B的引用计数都为1,永远不为零。按照引用计数法的规则,它们永远不会被回收,但实际上,它们已经是程序无法访问的垃圾了。

可达性分析算法的高明之处,就在于它从“根”出发的搜索方式,天然地绕过了这个陷阱。循环引用的对象组,只要它们整体无法从任何GC Root到达,就会被一网打尽,判定为可回收,从而完美解决了循环引用导致的“内存泄漏”问题。

判定过程会暂停程序吗?

会。而且这是一个关键点。在枚举所有GC Roots(即找出所有根对象)的这个初始阶段,JVM必须让整个程序“暂停”一下,这个动作被称为STW(Stop-The-World)

为什么要暂停?试想一下,如果在搜索根节点的过程中,程序还在不停地创建新对象、修改引用关系,那搜索结果就会错乱,可能导致该回收的没回收,不该回收的却被误杀。因此,为了保证分析结果的准确性,JVM需要让所有用户线程都到达一个安全点(SafePoint)并停下来,等根节点枚举这个“快照”拍完了,再恢复运行。

值得注意的是,这个STW的时间通常非常短暂。而且,在现代先进的垃圾收集器(如G1、ZGC)中,它们采用了更精巧的设计:仅在根节点枚举阶段进行短暂的STW,后续的标记过程(即沿着引用链遍历所有对象)是可以与用户程序并发执行的,从而极大地减少了停顿时间对应用的影响。

所以说,可达性分析不仅是JVM垃圾回收的理论基石,其实现细节(如短暂的STW)也深刻影响着应用程序的响应性能,是理解Ja va内存管理不可或缺的一环。

本文转载于:https://www.php.cn/faq/2422154.html 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。

热门关注