Java 销毁对象

      终结方法(finalizer)通常是不可预测的,也是很危险的,一般情况下是不必要的。使用终结方法会导致行为不稳定、降低性能,以及可移植性问题。
      在Java中完成这样的工作主要是依靠try-finally机制来协助完成的,然而Java中还提供了另外一种被称为finalizer的机制,使用者仅仅需要重载Object对象提供的finalize方法,这样当JVM的在进行垃圾回收时,就可以自动调用该方法。但是由于对象何时被垃圾收集的不确定性,以及finalizer给GC带来的性能上的影响,因此并不推荐使用者依靠该方法来达到关键资源释放的目的。比如,有数千个图形句柄都在等待被终结和回收,可惜的是执行终结方法的线程优先级要低于普通的工作者线程,这样就会有大量的图形句柄资源停留在finalizer的队列中而不能被及时的释放,最终导致了系统运行效率的下降,甚至还会引发JVM报出OutOfMemoryError的错误。

      Java的语言规范中并没有保证该方法会被及时的执行,甚至都没有保证一定会被执行。即便开发者在code中手工调用了 System.gc System.runFinalization 这两个方法,这仅仅是提高了finalizer被执行的几率而已。还有一点需要注意的是,被重载的finalize()方法中如果抛出异常,其栈帧轨迹是不会被打印出来的。在Java中被推荐的资源释放方法为,提供显式的具有良好命名的接口方法,如 FileInputStream.close() 和 Graphic2D.dispose() 等。然后使用者在finally区块中调用该方法,见如下代码:

public void test() {
    FileInputStream fin = null;
    try {
        fin = new FileInputStream(filename);
        //do something.
    } finally {
        fin.close();
    }
}
      在实际的开发中,利用finalizer又能给我们带来什么样的帮助呢?见下例:

public class FinalizeTest {
    //@Override
    protected void finalize() throws Throwable {
        try {
            //在调试过程中通过该方法,打印对象在被收集前的各种状态,
            //如判断是否仍有资源未被释放,或者是否有状态不一致的现象存在。
            //推荐将该finalize方法设计成仅在debug状态下可用,而在release
            //下该方法并不存在,以避免其对运行时效率的影响。
            System.out.println("The current status: " + _myStatus);
        } finally {
            //在finally中对超类finalize方法的调用是必须的,这样可以保证整个class继承
            //体系中的finalize链都被执行。
            super.finalize(); 
        }
    }
}

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。