浅析finalize方法

昨天有个小伙伴聊到java对象finalize方法。因而就想好好总结一下。java

我们都知道判断一个对象是否已经死了的方法有两种:程序员

1:引用计数法算法

2:可达性分析算法app

因为咱们一般使用的虚拟机使用的可达性分析算法,因此咱们这里聊的都是可达性分析算法的相关。ide

判断一个对象时生存仍是死亡???函数

即便在可达性分析算法中不可导的对象,也并不是就是‘非死不可’的,这时候咱们能够理解为改对象暂时处于“缓刑”阶段,跟死囚犯同样,仍是有机会不被砍头的。this

 

说明一个对象已经死亡,至少须要经历两个被标记过程:spa

 

若是对象在进行可达性分析后发现没有与GC Roots相链接的引用链,那它将会被第一次标记而且进行一次筛选,筛选的条件是此对象是否有必要执行finalize()方法。当对象没有覆盖finalize()方法,或者finalize()方法已经被虚拟机调用过,虚拟机将这两种状况都视为“没有必要执行”。线程

 

若是这个对象被断定为有必要执行finalize()方法,那么这个对象将会放置在一个叫作orm

F-Queue的队列之中,并在稍后由一个由虚拟机自动创建的、低优先级的Finalizer线程去执行它。这里所谓的“执行”是指虚拟机会触发这个方法,但并不承诺会等待它运行结束,这样作的缘由是,若是一个对象在finalize()方法中执行缓慢,或者发生了死循环(更极端的状况),将极可能会致使F-Queue队列中其余对象永久处于等待,甚至致使整个内存回收系统崩溃。finalize()方法是对象逃脱死亡命运的最后一次机会,稍后GC将对F-Queue中的对象进行第二次小规模的标记,若是对象要在finalize()中成功拯救本身——只要从新与引用链上的任何一个对象创建关联便可,譬如把本身(this关键字)赋值给某个类变量或者对象的成员变量,那在第二次标记时它将被移除出“即将回收”的集合;若是对象这时候尚未逃脱,那基本上它就真的被回收了

 

Finalize方法具备如下四个特色:

  1. 永远不要主动调用某个对象的finalize方法,该方法应该交给垃圾回收机制调用。

  2. Finalize方法合适被调用,是否被调用具备不肯定性,不要把finalize方法当作必定会执行的方法,

  3. 当JVM执行课恢复对象的finalize方法时,多是改对象或系统中其余对象从新变成可达状态

  4. 当JVM调用finalize方法出现异常时,垃圾回收机制不会报告异常,程序继续执行。

 


注意点:

因为finalize方法不必定被执行,那么咱们想清理某各种里打开的资源时,则不要方法finalize方法中。


实例说明:


运行结果能够看出,SAVE_HOOK对象的finalize()方法确实被GC收集器触发过,而且在被收集前成功逃脱了。另一个值得注意的地方是,代码中有两段彻底同样的代码片断,执行结果倒是一次逃脱成功,一次失败,这是由于任何一个对象的finalize()方法都只会被系统自动调用一次,若是对象面临下一次回收,它的finalize()方法不会被再次执行,所以第二段代码的自救行动失败了。

须要特别说明的是,上面关于对象死亡时finalize()方法的描述可能带有悲情的艺术色

彩,笔者并不鼓励你们使用这种方法来拯救对象。相反,笔者建议你们尽可能避免使用它,由于它不是C/C++中的析构函数,而是Java刚诞生时为了使C/C++程序员更容易接受它所作出的一个妥协。它的运行代价高昂,不肯定性大,没法保证各个对象的调用顺序。有些教材中描述它适合作“关闭外部资源”之类的工做,这彻底是对这个方法用途的一种自我安慰。finalize()能作的全部工做,使用try-finally或者其余方式均可以作得更好、更及时,因此笔者建议你们彻底能够

忘掉Java语言中有这个finalize方法的存在。

相关文章
相关标签/搜索