示意图
先来看示意图
root就是变量,非堆对象。
非堆对象包含什么?很显然,就是线程栈的方法的局部变量和方法区的类静态变量。
所以,root就是线程栈的方法的局部变量和方法区的类静态变量。
如何判断对象已死?
可达性分析的作用,就是判断对象是否已死。
核心就是上面的示意图,但是光看图,根本都不知道什么意思。如果只是用文字解释,其实也不知道是什么意思。
所以,必须要结合代码理解,否则说了半天,都是废话。
那上面的示意图到底是啥意思呢?
核心是gc root。这个只是一个名字而已,看这个名字,其实也不知道是啥意思。
那root到底是啥呢?其实就是一个变量。比如方法里的局部变量。
看代码
publicclass Test {
public static void main(String[] args) {
Test a = new Test(); //变量a就是root
a = null; //a置为null之后,就没有变量指向刚刚创建的对象
}
}
变量a就是root,指向new创建的对象(假设是对象1)。对象1被变量a指向,所以对象1是活的,不能被回收。但是,把a置为null之后,a就不再指向对象1,这个时候没有任何变量指向对象1,所以对象1就死了,可以被回收。
可达性分析也是基于引用
变量a指向对象1,其实就是变量a引用了对象1。所以,可以发现,所谓的可达性分析算法其实也是基于引用,这个和引用计数算法是一样的,都是基于引用。
总结
所以,引用计数算法是,有变量引用就加1。如果没有变量引用,计数就是0,表示对象已死。
可达性分析是,是否有变量引用。如果没有变量引用,表示对象已死。
这么描述,好像二者差不多,都是通过是否有变量引用,来判断对象是否已死。确实差不多,因为本来二者都是基于引用来判断。只不过实现的算法有区别,一个是计数,一个是可达性。
哪些变量可以作为root?
主要包括下面几种:
1、 线程栈的方法的局部变量
2、 方法区中的类静态变量
3、 方法区中的字符串字面量变量
具体的代码例子,可以参考: