欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Java禁止使用finalize方法

程序员文章站 2024-02-24 21:29:34
什么是finalize方法 finalize()方法被定义在java.lang.object类中,意味着所有的类都可以重载这个方法。java垃圾回收器只之道释放那些经由n...

什么是finalize方法

finalize()方法被定义在java.lang.object类中,意味着所有的类都可以重载这个方法。java垃圾回收器只之道释放那些经由new分配的内存,所以如果你的对象并非通过new获得的内存,那么垃圾回收器就不知道如何释放该对象的内存了。

为了应对这种情况,java允许在类中重载java.lang.object类中的finalize()方法。

它的工作原理:一旦垃圾回收器准备好释放对象占用的存储空间,将首先调用其finalize()方法,并且在下一次垃圾回收动作发生时,才会真正回收对象占用的内存。

finalize函数的调用机制

java虚拟机规范并没有硬性规定垃圾回收该不该搞,以及该如何搞。所以这里提到的调用机制不能保证适合所有jvm。

何时被调用?

  finalize啥时候才会被调用捏?一般来说,要等到jvm开始进行垃圾回收的时候,它才有可能被调用。而jvm进行垃圾回收的时间点是非常不确定的,依赖于各种运行时的环境因素。正是由于finalize函数调用时间点的不确定,导致了后面提到的某些缺点。

谁来调用?

  常见的jvm会通过gc的垃圾回收线程来进行finalize函数的调用。由于垃圾回收线程比较重要(人家好歹也是jvm的一个组成部分嘛),为了防止finalize函数抛出的异常影响到垃圾回收线程的运作,垃圾回收线程会在调用每一个finalize函数时进行try catch,如果捕获到异常,就直接丢弃,然后接着处理下一个失效对象的finalize函数。

为什么禁止使用finalize()

1.调用时间不确定---有资源浪费的风险

前面已经介绍了调用机制。同学们应该认清“finalize的调用时机是很不确定的”这样一个事实。所以,假如你把某些稀缺资源放到finalize()中释放,可能会导致该稀缺资源等上很久很久很久以后才被释放。这可是资源的浪费啊!另外,某些类对象所携带的资源(比如某些jdbc的类)可能本身就很耗费内存,这些资源的延迟释放会造成很大的性能问题。

2.可能不被调用----有资源泄露的风险

很多同学以为finalize()总是会被调用,其实不然。在某些情况下,finalize()压根儿不被调用。比如在jvm退出的当口,内存中那些对象的finalize函数可能就不会被调用了。

估计有同学在打“runfinalizersonexit”的主意,来确保所有的finalize在jvm退出前被调用。很可惜也很遗憾,该方法从jdk 1.2开始,就已经被废弃了。即使该方法不被废弃,也是有很大的线程安全隐患滴!   

从上述可以看出,一旦你依赖finalize()来帮你释放资源,那可是很不妙啊(有资源泄漏的危险)!很多时候,资源泄露导致的性能问题更加严重,万万不可小看。

3.对象可能在finalize函数调用时复活

本来,只有当某个对象已经失效(没有引用),垃圾回收器才会调用该对象的finalize函数。但是,万一碰上某个变态的程序员,在finalize()函数内部再把对象自身的引用(也就是this)重新保存在某处,也就相当于把自己复活了(因为这个对象重新有了引用,不再处于失效状态)。 为了防止发生这种诡异的事情,垃圾回收器只能在每次调用完finalize()之后再次去检查该对象是否还处于失效状态。这无形中又增加了jvm的开销。随便提一下。由于jdk的文档中规定了,jvm对于每一个类对象实例最多只会调用一次finalize()。所以,对于那些诈尸的实例,当它们真正死亡时,finalize()反而不会被调用了。这看起来是不是很奇怪?

4.要记得自己做异常捕获

刚才在介绍finalize()调用机制时提到,一旦有异常抛出到finalize函数外面,会被垃圾回收线程捕获并丢弃。也就是说,异常被忽略掉了(异常被忽略的危害,“这里”有提到)。为了防止这种事儿,凡是finalize()中有可能抛出异常的代码,你都得写上try catch语句,自己进行捕获。

5.小心线程安全

由于调用finalize()的是垃圾回收线程,和你自己代码的线程不是同一个线程;甚至不同对象的finalize()可能会被不同的垃圾回收线程调用(比如使用“并行收集器”的时候)。所以,当你在finalize()里面访问某些数据的时候,还得时刻留心线程安全的问题。

总结

以上所述是小编给大家介绍的java禁止使用finalize方法,希望对大家有所帮助