上篇文章讲到,虚拟机判断一个对象是否可回收是根据“可达性分析”,不可达的对象就是可回收的对象,但是被判定为“不可达的对象”也并非“非死不可”。它们只是被判了“缓刑”,最后是死是生都有可能。
我们看看回收无效对象的过程:
对象经过可达性分析后,发现没有被
GC Roots
关联,则会被第一次标记。判断对象是否覆盖了finalize方法。
如果覆盖了该方法,并且该对象的finalize
方法还没有执行过。则将这个对象放到F-Queue
队列中,稍后虚拟机将启动一个优先级比较低的Finalizer线程去执行finalize方法。
如果没有覆盖该方法,或者说finalize
方法已经执行过了,则对象就只能等死(等待垃圾收集器将其回收)
- 执行F-Queue队列中等待执行的finalize方法
Finalizer线程执行F-Queue
队列中的finalize
方法时,将是对象自救的最后一次机会。如果方法的执行使得对象被其他变量或对象所引用,则GC Roots
变为可达,GC将会把它移出“即将回收”的对象集合。如果它没有自救,那它就只能等待回收了。
- 回收“即将回收”的集合中的所有对象
垃圾回收器将基于其采用的回收算法,对无用对象进行回收。
说说finalize方法
从上面的过程中,可以看出,一个类如果定义了finalize
方法,在垃圾回收其实例的过程,会先执行finalize
方法。
那么,是不是意味着我们可以再finalize
方法中进行资源释放呢?
这样做是很危险的。因为在执行F-Queue
队列中的finalize
方法时,虚拟机并不承诺完整地执行完整个方法。因为如果finalize
方法中执行的操作比较耗时,虚拟机将终止它以保证队列中其他finalize
方法能够及时执行。
因此,释放资源还是选择try - finally
的方式吧。
另外,对象自救的方法也不建议利用finalize方法,因为finalize只会被系统调用一次,对象可能活过第一次,但是却可能活不过第二次的垃圾回收,因为第二次时finalize将不再执行。
总之,finalize方法了解就好,实际情况中不建议使用。
点赞是对我最大的鼓励