什么是垃圾收集器的GC Roots?它们有哪些类型?代码举例讲解

GC Roots是垃圾回收器用来判断对象是否可达的起始点。它们包括:

  1. 虚拟机栈中引用的对象:如本地变量、方法参数等。
  2. 方法区中类静态属性引用的对象。
  3. 方法区中常量引用的对象。
  4. 本地方法栈中JNI(Java Native Interface)引用的对象。

这些GC Roots作为根节点,垃圾回收器会从它们开始遍历,判断哪些对象可以从GC Roots直接或间接的访问到,这些对象就是可达对象,不会被回收。其他不可达对象则会被回收。
GC Roots主要分类有:

  1. 本地方法栈中的GC Roots:包括JNI局部引用的Java对象等。
  2. 虚拟机栈GC Roots:包括本地变量表中引用对象的句柄等。
  3. JNI全局引用表中的GC Roots。
  4. 类静态属性引用的GC Roots。
  5. 常量引用的GC Roots。

来看一个简单示例:

public class GCDemo {
    private static Object obj1;
    private final static Object obj2 = new Object();

    public static void main(String[] args) {
        Object obj3 = new Object();
        obj1 = obj3;

        method1();

        obj3 = null;   // obj3可回收

        obj1 = null;   // obj1不可回收,被类静态属性obj1引用

        obj2 = null;   // obj2不可回收,被常量obj2引用
    }

    public static void method1() {
        Object obj4 = new Object();
    }  // obj4可回收,超出作用域被回收
}

在该示例中:

  1. obj3作为GC Roots,obj1可达,不会回收。
  2. 方法执行完,obj4超出作用域,可回收。
  3. obj1作为类静态属性,作为GC Roots,obj1不可回收。
  4. obj2作为常量,也作为GC Roots,obj2不可回收。