GC Roots是垃圾回收器用来判断对象是否可达的起始点。它们包括:
- 虚拟机栈中引用的对象:如本地变量、方法参数等。
- 方法区中类静态属性引用的对象。
- 方法区中常量引用的对象。
- 本地方法栈中JNI(Java Native Interface)引用的对象。
这些GC Roots作为根节点,垃圾回收器会从它们开始遍历,判断哪些对象可以从GC Roots直接或间接的访问到,这些对象就是可达对象,不会被回收。其他不可达对象则会被回收。
GC Roots主要分类有:
- 本地方法栈中的GC Roots:包括JNI局部引用的Java对象等。
- 虚拟机栈GC Roots:包括本地变量表中引用对象的句柄等。
- JNI全局引用表中的GC Roots。
- 类静态属性引用的GC Roots。
- 常量引用的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可回收,超出作用域被回收
}
在该示例中:
- obj3作为GC Roots,obj1可达,不会回收。
- 方法执行完,obj4超出作用域,可回收。
- obj1作为类静态属性,作为GC Roots,obj1不可回收。
- obj2作为常量,也作为GC Roots,obj2不可回收。