class Object {
...
protected void finalize() throws Throwable { }
}
finalize()方法是Object类的一个protected方法,所以所有的类都可以调用Object类的finalize()方法,也可以自己去重写finalize()方法。
GC对不可达对象的两次扫描
首先需要知道的是大多数虚拟机会使用可达性算法来判断对象是否有引用,如果没有引用的话,会进行两轮标记。
首先第一轮标记会判断对象:
- 1.重写了finalize()方法
- 2.没有调用finalize()方法
只要上面两个条件都成立,那么这个对象就会被放置在一个F-Queue的队列中,然后由一个低优先级的Finalizer线程去执行队列中对象重写的finalize()方法。
为了避免GC长时间等待,Finalizer线程执行队列中对象重写的finalize()方法不保证方法能够及时执行以及执行成功。
稍后GC会对F-Queue队列中的对象进行第二次扫描,如果队列中的对象在执行finalize()方法之后变得可达(重新与引用链上的对象建立关系),那么这个对象将从”待回收队列”中移除。
两次扫描之后还在”待回收队列”中的对象将被GC回收。
通过上面的分析可以得出finalize()方法执行的几个结论:
- 1.只有重写了finalize()方法的类的对象的finalize()方法才会在第一次扫描的时候被执行
- 2.由于Finalizer线程优先级低,所以即使重写了finalize()方法,GC也不保证对象的finalize()方法会被及时执行以及执行成功,哪怕经历多次GC
- 3.一个对象的finalize()方法只会被执行一次,这里说的一次指的是虚拟机自己调用,自己代码中手动调用想调几次调几次
- 4.finalize()方法是对象逃离被回收最后的机会,如果对在finalize()方法执行之后没有变成可达,将彻底被回收
finalize()方法的作用分析
由于finalize()方法在对象被回收之前会被调用,所以finalize()方法在有些地方会被用来关闭外部资源。
但是由于finalize()方法被调用的不确定性,所以强烈不建议使用finalize()方法来关闭外部资源。
能使用finalize()方法来关闭的外部资源,使用try-finally来关闭可以做的更好、更及时。
所以今天这篇文章的总结就是大家完全可以忘记finalize()方法的存在,这个方法并没有什么卵用。
喜欢这篇文章的朋友,欢迎扫描下图关注公众号lebronchen,第一时间收到更新内容。