其他分享
首页 > 其他分享> > JVM - finalize()方法的原理

JVM - finalize()方法的原理

作者:互联网

总结

1.当JVM通过GC Roots可达性分析,判断某对象可以被回收后,会判断是否重写了finalize方法,如果没有,直接回收

2.如果重写了,把该对象放入F-Queue队列,有线程(一个级别很低的daemon线程)专门遍历并执行这些的finalize方法

3.执行finalize()后,等下一次GC时再判断该类是否可被回收,如果是就回收

 

override finalize()函数的风险:

 

详细

我们现在来看一下自定义了(override)finalize()的对象(或是某个父类override finalize())是怎样被GC回收的,首先需要注意的是,含有override finalize()的对象A创建要经历以下3个步骤:

经过上述三个步骤,我们建立了这样的一个引用关系:

java.lang.ref.Finalizer–>F1–>A,F1–>ReferenceQueue。GC过程如下所示:

 

有override finalize()对象的minor gc

如上图所示,在发生minor gc时,即便一个对象A不被任何其他对象引用,只要它含有override finalize(),就会最终被java.lang.ref.Finalizer类的一个对象F1引用,等等,如果新生代的对象都含有override finalize(),那岂不是无法GC?没错,这就是finalize()的第一个风险所在,对于刚才说的情况,minor gc会把所有活跃对象以及被java.lang.ref.Finalizer类对象引用的(实际)垃圾对象拷贝到下一个survivor区域,如果拷贝溢出,就将溢出的数据晋升到老年代,极端情况下,老年代的容量会被迅速填满,于是让人头痛的full gc就离我们不远了。

那么含有override finalize()的对象什么时候被GC呢?例如对象A,当第一次minor gc中发现一个对象只被java.lang.ref.Finalizer类对象引用时,GC线程会把指向对象A的Finalizer对象F1塞入F1所引用的ReferenceQueue中,java.lang.ref.Finalizer类对象中包含了一个运行级别很低的daemon线程finalizer来异步地调用这些对象的finalize()方法,调用完之后,java.lang.ref.Finalizer类对象会清除自己对F1的引用。这样GC线程就可以在下一次minor gc时将对象A回收掉。

也就是说一次minor gc中实际至少包含两个操作:

可见Finalizer对象的多少也会直接影响minor gc的快慢。

包含有自定义finalizer方法的对象回收过程总结下来,有以下三个风险:

以上的三点还没有考虑minor gc时为了分辨哪些对象只被java.lang.ref.Finalizer类对象引用的开销,讲完了finalize()原理,我们回头看看最初的那句话:JVM能够保证一个对象在回收以前一定会调用一次它的finalize()方法。

含有override finalize()的对象在会收前必然会进入F QUEUE,但是JVM本身无法保证一个对象什么时候被回收,因为GC的触发条件是需要GC,所以JVM方法不保证finalize()的调用点,如果对象一直不被回收,就一直不调用,而调用了finalize(),也不代表对象就被回收了,只有到了下一次GC时该对象才能真正被回收。另外一个关键点是一次,在调用过一次对象A的finalize()之后,就解除了Finalizer类对象和对象F1之间的引用关系,如果在finalize()中又将对象本身重新赋给另外一个引用(对象拯救),那这个对象在真正被GC前是不会再次调用finalize()的。

总结一下finalize()的两个个问题:

回到最初的问题,对于那些需要释放资源的操作,我们应该怎么办?effective java告诉我们,最好的做法是提供close()方法,并且告知上层应用在不需要该对象时一掉要调用这类接口,可以简单的理解这类接口充当了析构函数。当然,在某些特定场景下,finalize()还是非常有用的,例如实现一个native对象的伙伴对象,这种伙伴对象提供一个类似close()接口可能不太方便,或者语义上不够友好,可以在finalize()中去做native对象的析构。不过还是那句话,fianlize()永远不是必须的,千万不要把它当做析构函数,对于一个对性能有相当要求的应用或服务,从一开始就杜绝使用finalize()是最好的选择。

标签:F1,finalize,对象,Finalizer,GC,JVM,override,原理
来源: https://www.cnblogs.com/frankcui/p/14157556.html