深入学习JVM 【4】回收“已死”对象的过程

上篇文章讲到,虚拟机判断一个对象是否可回收是根据“可达性分析”,不可达的对象就是可回收的对象,但是被判定为“不可达的对象”也并非“非死不可”。它们只是被判了“缓刑”,最后是死是生都有可能。

我们看看回收无效对象的过程:

  1. 对象经过可达性分析后,发现没有被GC Roots关联,则会被第一次标记

  2. 判断对象是否覆盖了finalize方法

如果覆盖了该方法,并且该对象的finalize方法还没有执行过。则将这个对象放到F-Queue队列中,稍后虚拟机将启动一个优先级比较低的Finalizer线程去执行finalize方法。

如果没有覆盖该方法,或者说finalize方法已经执行过了,则对象就只能等死(等待垃圾收集器将其回收)

  1. 执行F-Queue队列中等待执行的finalize方法

Finalizer线程执行F-Queue队列中的finalize方法时,将是对象自救的最后一次机会。如果方法的执行使得对象被其他变量或对象所引用,则GC Roots变为可达,GC将会把它移出“即将回收”的对象集合。如果它没有自救,那它就只能等待回收了。

  1. 回收“即将回收”的集合中的所有对象

垃圾回收器将基于其采用的回收算法,对无用对象进行回收。

说说finalize方法

从上面的过程中,可以看出,一个类如果定义了finalize方法,在垃圾回收其实例的过程,会先执行finalize方法。

那么,是不是意味着我们可以再finalize方法中进行资源释放呢?

这样做是很危险的。因为在执行F-Queue队列中的finalize方法时,虚拟机并不承诺完整地执行完整个方法。因为如果finalize方法中执行的操作比较耗时,虚拟机将终止它以保证队列中其他finalize方法能够及时执行。

因此,释放资源还是选择try - finally的方式吧。

另外,对象自救的方法也不建议利用finalize方法,因为finalize只会被系统调用一次,对象可能活过第一次,但是却可能活不过第二次的垃圾回收,因为第二次时finalize将不再执行。

总之,finalize方法了解就好,实际情况中不建议使用。

点赞是对我最大的鼓励

你可能感兴趣的:(深入学习JVM 【4】回收“已死”对象的过程)