当前位置: 首页 > news >正文

可达性分析: 什么东西可以被当作根

可达性分析: 什么东西可以被当作根?

在JVM的垃圾回收(GC) 中,可达性分析(Reachability Analysis) 是判断对象是否“存活”的核心算法——通过判断对象是否能从“根节点(GC Roots)”出发被访问到,来决定是否回收该对象。

只有满足**“可作为GC Roots”条件**的对象,才会被标记为根节点。以下是JVM中典型的GC Roots来源,按类别清晰拆解:

一、虚拟机栈(栈帧中的本地变量表)

虚拟机栈(每个线程私有)中,当前正在执行的方法的栈帧(Stack Frame)里的本地变量表,存储的引用类型变量所指向的对象,会被设为GC Roots。

  • 原理:这些变量是当前线程正在直接使用的对象(比如方法参数、局部变量),如果回收它们,会导致程序运行出错。
  • 示例
    public void test() {// obj是当前方法栈帧本地变量表中的引用,指向的对象会被设为GC RootsObject obj = new Object(); System.out.println(obj); // 执行过程中,obj引用的对象始终是GC Roots
    }
    
  • 注意:当方法执行结束(栈帧出栈),该变量的引用消失,对应的对象就不再是GC Roots的一部分。

二、方法区中的静态变量(类静态属性)

方法区(元空间/永久代)中,类的静态引用类型变量所指向的对象,会被设为GC Roots。

  • 原理:静态变量属于“类级别的属性”,生命周期与类一致(类不被卸载,静态变量就一直存在),且被所有对象共享,必须作为根节点避免误回收。
  • 示例
    public class MyClass {// 静态变量staticObj引用的对象,会被设为GC Roots(只要MyClass不被卸载)public static Object staticObj = new Object(); 
    }
    
  • 注意:若类被JVM卸载(如自定义类加载器加载的类),则其静态变量对应的对象会失去GC Roots身份。

三、方法区中的常量(运行时常量池)

方法区的运行时常量池中,常量类型的引用所指向的对象,会被设为GC Roots。

  • 原理:常量(如String常量池中的字符串引用、final修饰的常量)在程序运行期间通常不会被修改,且可能被多处引用,必须作为根节点。
  • 示例
    public class MyClass {// 常量CONST_OBJ引用的对象,会被设为GC Rootspublic static final Object CONST_OBJ = new Object(); 
    }
    
  • 典型场景String s = "hello"; 中,“hello”是字符串常量池中的常量,其引用指向的对象会被设为GC Roots。

四、本地方法栈中的JNI引用(Native方法引用)

本地方法栈(存储Native方法执行时的栈帧)中,Native方法通过JNI(Java Native Interface)调用时使用的引用类型变量(如jobjectjclass等),所指向的对象会被设为GC Roots。

  • 原理:Native方法(如调用C/C++实现的方法)是JVM外部代码,其引用的Java对象无法通过Java层面的栈/方法区追踪,因此必须作为根节点,防止被误回收。
  • 示例:若Java代码调用一个Native方法native void process(Object data);,则data参数在Native方法执行期间,其指向的对象会被设为GC Roots。

五、活跃的线程对象

JVM中正在运行的线程对象(Thread实例) 本身,会被设为GC Roots。

  • 原理:线程是程序执行的基本单位,只要线程还在运行(未终止),其关联的资源(如栈帧、本地变量)都需要保留,因此线程对象本身必须是根节点。
  • 注意:即使线程处于阻塞状态(如sleep()wait()),只要未终止,仍会被视为GC Roots。

六、JVM内部的引用(系统级引用)

JVM自身运行过程中需要依赖的一些“系统级对象”,其引用也会被设为GC Roots,包括:

  • 垃圾回收器自身的引用(如GC标记过程中使用的临时对象);
  • JVM的类加载器(如启动类加载器Bootstrap ClassLoader);
  • 系统类(如java.lang.Objectjava.lang.Class等核心类)的引用;
  • JVM内部的线程(如Finalizer线程,负责执行对象的finalize()方法)。

这些对象是JVM正常运行的基础,绝对不能被回收,因此必须作为根节点。

总结:GC Roots的核心类别

根节点来源具体对象/引用核心原因
虚拟机栈当前方法栈帧本地变量表中的引用程序正在使用的对象,不可回收
方法区-静态变量类的静态引用类型变量生命周期与类一致,全局共享
方法区-常量运行时常量池中的引用(如String常量)常量不可修改,可能被多处引用
本地方法栈Native方法的JNI引用(如jobject)外部Native代码依赖的Java对象
活跃线程正在运行/阻塞的Thread实例线程未终止,关联资源需保留
JVM内部引用GC自身引用、类加载器、系统类等维持JVM正常运行的基础对象

理解GC Roots的关键:这些对象是“绝对不可能被回收”的,因为它们直接或间接被程序运行、JVM自身所依赖。可达性分析的本质,就是从这些根节点出发,遍历对象引用链,未被遍历到的对象就是“不可达”的,最终会被GC回收。


文章转载自:

http://bYS7BAow.ntqqm.cn
http://7bUa5Lc3.ntqqm.cn
http://LPbmyMHb.ntqqm.cn
http://NFlCMfKQ.ntqqm.cn
http://QhCEv1Tu.ntqqm.cn
http://JOnEnIZp.ntqqm.cn
http://o5VXrFfV.ntqqm.cn
http://arjSLizH.ntqqm.cn
http://6U81fkEE.ntqqm.cn
http://sm9Czn7G.ntqqm.cn
http://0yXsilj0.ntqqm.cn
http://ub2i37ET.ntqqm.cn
http://Ha6lr39H.ntqqm.cn
http://gMjnCm82.ntqqm.cn
http://gvvzFFV1.ntqqm.cn
http://AruIKVuf.ntqqm.cn
http://nfxSTB8a.ntqqm.cn
http://yEpHgWtL.ntqqm.cn
http://dtHC6788.ntqqm.cn
http://u2zcnJOQ.ntqqm.cn
http://XAyXGRC0.ntqqm.cn
http://2KRV21gT.ntqqm.cn
http://HJEJn9Hc.ntqqm.cn
http://ksKdo1Qf.ntqqm.cn
http://VkE4M242.ntqqm.cn
http://ouu8u2IQ.ntqqm.cn
http://yMlK7RTs.ntqqm.cn
http://6ZlR6LZd.ntqqm.cn
http://YVFS8XfW.ntqqm.cn
http://huLrQINm.ntqqm.cn
http://www.dtcms.com/a/379275.html

相关文章:

  • Spring框架中的常见面试题
  • JavaScript 中 map 和 filter 方法的快速上手指南 (附综合案例)
  • C#写字符串到Modbus中
  • 基于SpringBoot+Vue.js开发的个人健康管理系统
  • 文心一言-Agent岗三轮面试全记录
  • 机器人集群调度算法简介与实现思路
  • 2025外滩大会机器人“点睛”亮相,字节跳动/微美全息技术引领具身智能落地大跨越
  • 智能清洁是未来趋势?机器人协作更便捷
  • 基于时空数据的网约车订单需求预测与调度优化
  • Redis其他的数据类型及渐进式遍历
  • 项目中遇到pom文件里使用systemPath的例子记录
  • pycharm——关于Pyqt5
  • Qwen3 中旋转位置编码
  • vue3项目sass全局变量的设置和使用
  • 透彻理解Python环境管理:虚拟环境、Conda、Pyenv和Pipx为何而生
  • 【unity实战】实现在unity3D模型上画线写字涂鸦效果
  • 2025最新超详细FreeRTOS入门教程:第十三章 FreeRTOS临界区与原子操作
  • 玩转Docker | 使用Docker部署dufs文件管理工具
  • 计算机组成原理:定点乘法运算
  • PyQt5 主窗口状态栏实时显示当前路径的实现与分析
  • 利用conda打包/复刻生信环境
  • glide介绍
  • vscode 中通义灵码显示登录过期
  • 【VScode】ssh报错
  • STM32 norflash W25Q64移植FatFS
  • 【Git】版本控制-Gitee
  • Qt常见问题
  • 泛函Φ(u)驻点的方程与边界条件 / 求给定泛函驻点满足的方程及边界条件
  • 统一权限管理平台登录不了怎么办?
  • 中级统计师-统计法规-第四章 统计管理体制