可达性分析算法

2023-07-27 jvm

可达性分析算法也称为引用链法(GCRoots) ,它的核心目的就是判断Java对象是否存活?

相对于引用计数算法而言,可达性分析算法不仅同样具备实现简单和执行高效等特点,更重要的是该算法可以有效地解决在引用计数算法中循环引用的问题,防止内存泄漏的发生。

实现思路:基本思路就是通过一系列名为"GCRoots"的对象作为起始点从这个被称为GC Roots的对象开始向下搜索,如果一个对象到GCRoots没有任何引用链相连时,则说明此对象不可用。也即给定一个集合的引用作为根出发,通过引用关系遍历对象图,能被遍历到的(可到达的)对象就被判定为存活,没有被遍历到的就自然被判定为不可达(暂时处于“缓刑”阶段)。

可达性分析算法

什么是GCRoots?

所谓"GCroots,或者说tracingGC的“根集合” 就是一组必须活跃的引用。

# 哪些对象可以作为GCRoots?

  1. 栈帧:虚拟机栈(栈帧中的本地变量表)中引用的对象(PS:可以理解为引用栈帧中的本地变量表的所有对象)。
  2. 方法区:
    • 方法区中静态属性引用的对象,可以理解为引用方法区该静态属性的所有对象
    • 方法区中常量引用的对象,可以理解为引用方法区中常量的所有对象
  3. 本地方法栈:本地方法栈中(Native方法)引用的对象(可以理解为:引用Native方法的所有对象)

GCRoots存储的对象

# 举例说明

如下图所示,灰色的是GCRoots,根据GCRoots在堆中通过可达性分析算法找到存活对象,那么obj2和obj3是可回收对象(垃圾对象);当然,图中还有一个特点是,第一行的两个区域是线程共享的,第二行的3个区域是线程私有的。

GCRoots存储的对象案例

# 可达性分析算法如何判定一个对象是否死亡?

上文只能找到可回收对象(垃圾对象),但并不能判定它就是死亡对象,此时还不能进行销毁

可达性分析算法判断对象死亡

如何复活已死亡的对象?

重写类的finalize()方法,将对象重新赋值。

# 关于finalize()方法

  1. 调用finalize()方法的时机是当JVM确定不再有指向该对象的引用时,垃圾收集器在对象上调用该方法。
  2. finalize(方法的作用: JVM 调用该方法,表示该对象即将“死亡”,之后JVM就可以回收该对象了。有点类似对象生命周期的临终方法。
  3. 通过使用finalize方法可以实现对象的自我拯救,但是只能拯救一次
  4. 打开jvisualvm查看Finalizer线程
上次更新: 5 个月前