谁才是真正的垃圾:判断可触及性
垃圾回收的基本思想是考察每一个对象的可触及性,即 从跟节点开始是否可以访问到这个对象,如果可以,则说明当前对象正在被使用,如果所有的根节点都无法访问到某个对象,说明对象已经不再使用了,一般来说,这个对象需要被回收。但事实上,一个无法触及的对象有可能在某一条件下复活自己,如果这样,那么对它的回收就是不合理的,为此需要给出一个对象可触及性的状态的定义,并规定在什么状态下,才可以被回收
简单来说:可触及性包含三种状态
→ 可触及的:从根节点开始,可以到达这个对象。
→ 可复活的:对象的所有引用都被释放,但是对象有可能在finalize()函数中复活。
→ 不可触及的:对象的finalize()函数被调用,并且没有复活,那么就会进入不可触及状态,不可触及的对象不可能被复活,因为finalize()函数只会被调用一次。 下面给出在finalize()函数中有可能复活自己的对象 的例子
这里obj复活了,真正的原因在第9行代码,因为第一次gc处理时,在finalize()函数调用之前,虽然系统中的引用已经被清除,但是作为实例方法finalize(),对象的this引用依然会被传入方法内部,如果引用外泄,对象就会复活自己,此时,对象又变成可触及的状态。而finalize()函数只会被调用一次,因此,第二次清除对象的时候,对象就再无激活复活,因此就会被回收掉。
注意:finalize()函数是个非常糟糕的设计模式,不推荐使用finalize()函数释放资源。
→ 第一,因为finalize()函数有可能发生引用外泄,在无意中复活对象。
→ 第二,由于finalize()函数是被系统调用的,调用时间是不明确的,因此不是一个好的资源释放方案,推荐在try-catch-finally语句中进行资源释放。