在阅读《深入理解java虚拟机》之前,就曾看过JVM通过引用计数算法来判断一个对象的存活状态这种结论,事实上并非如此,此书作者也用实例证明此结论的错误。引用计数算法意思是当一个对象被另一个地方引用时,计数器的值+1,引用失效后,值-1。实例中使用两个对象相互引用,可还是被回收了。
真正的判断方法应该是可达性分析算法,即通过一系列的称为"引用链"来判断存货状态,引用链的最顶级为“GC Roots”,作为起点,当一个对象与GC Roots没有任何引用链相连接,说明该对象不可用,会被判定为可回收对象。
上图右边的object5、object6、object7均没有引用链与GC Roots相连,即判断为不可达,就会被判定为可回收的对象。
在java语言中,可以作为GC Roots的对象包括:
–虚拟机栈(栈中的本地变量表)中引用的对象
–方法区中类静态属性引用的对象
–方法区中常量引用的对象
–本地方法栈中(即一般说的Native方法)引用的对象
当一个对象被判定为可回收对象并不一定就是它会被回收,要让一个对象真正死亡必须经历两个标记程。第一个标记过程就是当一个对象与GC Roots为不可达时,第二次标记会进行一次筛选,筛选的条件是要不要执行finalize()方法,当对象没有重写finalize()方法或者此方法已经被虚拟机调用过,将不会执行此方法,其就是非死亡不可。但是要注意的是,一个对象的finalize()方法只会被执行一次,这次通过调用此方法也许可以不被回收,但下次它就一定会被回收。