为什么写这篇文章?
要说finalize方法我想做java的都知道,那么finalize方法会不会执行,如果会什么时候执行?如果重写finalize方法又有什么严重的后果?
为什么写这篇文章?
要说finalize方法我想做java的都知道,那么finalize方法会不会执行,如果会什么时候执行?如果重写finalize方法又有什么严重的后果?
题外话:以前看Java GC相关内容主要为的是应付面试而已,不过最近有个同事提了个问题(问题你么先YY),但他只说了对象会被回收,具体细节并没有说出,进而引发我再次探究GC
估计下次会以此问题展开讨论,由于我也是个菜鸟需要大家指出文章中的不足,谢谢!
Java finalize方法
finalize方法是Object类的方法,任何类都是重写finalize方法,实现自己想要的功能。
默认的finalize方法什么也没做
|
|
但是一般都不建议自己重写finalize方法,由于在清理对象时候无法保证finalize方法一定会被执行。
现在我们有一段小程序非常的简单,就是打印一句话,然后程序就结束了。
那么,对象会被回收吗?
什么时候执行GC我么是不清楚的,根据不同的算法有不同的调度,有的是根据时间调度,有的是根据
内存使用的情况进行调度。
不过让我来做的话,我更倾向于后者,不管运行多长时间只要内存没到我指定的阈值大小我就不执行,
现在的这个想法来源hadoop的spill,假设有100m的内存使用但是只要达到上限80m的内存用量,
那么我就开始执行GC。【只是我的想法,哈哈~】
那好,无论是根据时间又或者是内存大小进行GC,但是我么就一段输出代码,程序结束了估计也不会
执行GC线程进行清理吧!
没有执行GC也就是无法执行到finalize方法了。
那么,有什么方法可以执行gc呢?方法是有的,但是也不能保证一定会执行gc,只能说会催促进而执行
GC。
这也就是我么常说的
当然还存在其它方法,在最后我会将我参考链接发出。
那么,什么样的对象会被执行finalize方法呢?finalize方法又会被执行多少次呢?
对象销毁过程
对象的销毁过程中,按照对象的finalize执行情况,可以分为以下几种,系统会记录对象的
对应状态。
1、unfinalized 没有执行finalize,系统也不准备执行。
2、finalizable 可以执行finalize了,系统会在随后的某个时间执行finalize。
3、finalized该对象的finalize已经被执行了。
GC怎么来保持对finalizable的对象的追踪呢。GC有一个Queue,
叫做F-Queue,所有对象在变为finalizable的时候会加入到该Queue,然后等待GC执行它的
finalize方法。
这时我们引入了对对象的另外一种记录分类,系统可以检查到一个对象属于哪一种。
a.reachable:活动的对象引用链可以到达的对象,包括所有线程当前栈的局部变量,
所有的静态变量等等。
b.finalizer-reachable除了reachable外,从F-Queue可以通过引用到达的对象。
c.unreachable其它的对象
|
|
实践
|
|
|
|
|
|
|
|
输出如下:
|
|
可以看到的是我们在释放test1的时候成员对象test2也一起被回收了,由于test1重写了finalize
方法,在最后test1又复活了。
由于在GC Root中又有引用链起死回生,但是我么再一次设置null并执行gc可以看到test1对象
没有在进入finalize方法了。
总结
finalize方法不是每次都会执行的,使用System.gc()
也只不过是加快gc调用,并且重写finalize方法最好不要使对象再生,这样容易造成
对象的生命周期混乱!
参考
http://mazhuang.org/2015/12/15/java-object-finalize/
http://bijian1013.iteye.com/blog/2289661