《深入理解JVM》原文:
在主流的商用程序语言中(Java和C#),都是使用可达性分析算法判断对象是否存活的。这个算法的基本思路就是通过一系列名为GC Roots的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链(Reference Chain),当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的,下图对象object5, object6, object7虽然有互相判断,但它们到GC Roots是不可达的,所以它们将会判定为是可回收对象。
一般来说,如下情况的对象可以作为GC Roots:
- 虚拟机栈(栈桢中的本地变量表)中的引用的对象
- 方法区中的类静态属性引用的对象
- 方法区中的常量引用的对象
- 本地方法栈中JNI(Native方法)的引用的对象
我的理解:
可以看出,以上观点认为GC Roots是指对象,而我认为恰好相反,它指的应该是引用,不是堆中的对象。首先我们是能找虚拟机栈中的对象引用,也就是GC roots,通过它,我们能找到堆中被引用的对象,我们给他标记一次,然后顺着字段引用不断往下找,路径上的都标记一下。全部标记完成后,违背标记的就是不可达对象,进行回收。下面看一个简单的例子:
public static void main(String[] args) {
Object ref1 = new Object();
Object ref2 = new Object();
ref1 = ref2;
}
假设ref1指向的对象是堆中的对象instance1,ref2指向堆中的对象instance2,在第四行代码执行前后引用关系变化图如下:
所以GC Root set指的是应该是引用的集合,可以分为以下几种:
- 虚拟机栈(栈桢中的本地变量表)中的引用
- 方法区中的类静态属性引用
- 方法区中的常量引用
- 本地方法栈中JNI(Native方法)的引用
最后,以上为我个人观点,如果有误,欢迎各位大佬批评指正。