Java 的垃圾回收机制中不得不聊的GCRoot

你好,我是风一样的树懒,一个工作十多年的后端开发,曾就职京东、阿里等多家互联网头部企业。

点击下方👇关注公众号,带你一起复习后端技术,看看面试考点,补充积累技术知识,每天都为面试准备积累


在 Java 的垃圾回收机制(Garbage Collection)中,GC Root(根对象) 是一个非常重要的概念。它定义了 Java 虚拟机(JVM)中哪些对象作为垃圾回收的起点,从这些根对象出发,可以找到所有被引用的对象。



01
GC Root 的作用


在垃圾回收时,JVM 会通过 可达性分析算法 判断一个对象是否仍然被使用。可达性分析以一组作为 根(GC Root) 的对象为起点,通过递归方式检查其他对象的引用关系。如果某个对象没有与 GC Root 有直接或间接的引用链连接,就被判定为不可达,从而被认为是垃圾。


02
GC Root 的来源


GC Root 通常是一些特别的引用,它们的生命周期一般不会随程序的运行而变化。以下是 GC Root 的主要来源:

Java 栈(虚拟机栈)中的引用

  • 任何正在执行的线程中的局部变量或方法参数。

  • 这些引用通常存储在栈帧中的局部变量表中。

方法区中的静态变量

  • 定义在类中的 static 变量,例如:static String str = "Hello";。

  • 这些变量在类加载时存储在方法区中(Java 8 后存储在元空间)。

方法区中的常量引用

  • 比如常量池中的引用,字符串常量(如 "abc")或被引用的 final 常量。

  • 常量池在方法区中存在,因此常量池的引用也属于 GC Root。

本地方法栈中的 JNI 引用

    • 通过本地方法(如 C、C++ 代码)创建的对象引用,例如 JNIEnv 指针。

    活动线程

    • 所有存活的线程对象。

    类加载器

    • 加载类的类加载器本身可能作为根。

    JVM 内部的特殊引用

    • 如 JVM 中用于垃圾回收或运行时的一些特殊对象(系统类加载器、反射调用中创建的对象等)。


    03
    GC Root 的工作原理


    可达性分析算法:
    从 GC Root 出发,检查哪些对象可以被引用到,所有能通过引用链访问到的对象被认为是可达的,无法访问到的对象即不可达。
    • 引用链:对象之间的引用关系。

      标记-清除过程:

      • 在垃圾回收过程中,所有可达的对象被标记为存活对象。

      • 未被标记的对象会被认为是垃圾,清除这些对象并释放其占用的内存。


        04
        GC Root 示例


        示例代码:

        public class GCRootExample {    private static GCRootExample instance;        public static void main(String[] args) {        // 静态变量作为 GC Root        instance = new GCRootExample();        // 方法局部变量作为 GC Root        GCRootExample localVar = new GCRootExample();        // 调用垃圾回收        System.gc();    }}

        在上述代码中:

        • instance 是静态变量,作为 GC Root。

        • localVar 是局部变量,存储在栈中,也作为 GC Root。

        • 以 instance 和 localVar 为起点,找到的所有引用对象会被标记为可达对象。


        05
        GC Root 的意义


        垃圾回收的核心:GC Root 是垃圾回收的起点,决定了哪些对象会被清理,哪些会被保留。

        性能优化:合理设计 GC Root 的引用关系,能够提高垃圾回收的效率,减少内存泄漏。

        调试和分析:通过工具(如 VisualVM 或 MAT)分析 GC Root,可以帮助找到内存泄漏的根源。


        06
        总结


        GC Root 是可达性分析的起点,它是 JVM 判定对象是否存活的核心。

        GC Root 的主要来源包括栈中的引用、静态变量、常量引用、JNI 引用等。

        GC Root 的引用链连接的对象会被认为是存活对象,不会被垃圾回收。

        今天的内容就分享到这儿,喜欢的朋友可以关注,点赞。有什么不足的地方欢迎留言指出,您的关注是我前进的动力!

        END


        扫码关注

        一起积累后端知识
        不积跬步,无以至千里
        不积小流,无以成江海

        喜欢此内容的人还喜欢

        谈谈id那些事(五)——美团的 Leaf 的ID生成


        一个阿里二面面试官必问的问题


        Lambda表达式说爱你不容易


        分享面试:mysql数据库索引失效的情况


        Spring-Boot中一个不起眼的好工具StopWatch