public class AvoidFinalizer {
    /**
     *finalizer通常是不可预测的,危险的,一般也不必要,它会带来不稳定的行为、更差的性能及移植性问题
     *finalizer的不确定性(JLS不保证其会即时执行)——〉时间关键的任务不应该由finalizer来完成
     *及时执行finalizer是垃圾回收算法的功能,不同的JVM实现也不同——〉移植问题
     *finalizer的不确定性(JLS不保证其会被执行)——〉不应该依赖finalizer来更新关键性的永久状态,如
     *依赖于finalizer来释放一个共享资源(如数据库)上的永久锁
     */
    /**
     *Q:如果类封装的资源(如文件or线程)确实需要回收,应该怎么办才能finalizer
     *A:提供一个显式的终止方法(通常与try-finally结合,以确保及时执行),并要求该类的客户在每个实例不再需要时调用它,
     *InputStreamOutputStreamclose方法,Timer上的cancel方法,awt中的Graphics.disposeWindow.dispose
     */
    class Foo{    }

    Foo foo = new Foo();
    try{
       //...
    }finally{
       super.finalize();
       foo.terminate();
    }
    /**
     *Q:终结函数的好处呢?
     *A:1。当对象的所有者忘记调用显示的终止方法时,finalizer可以充当安全网(safety-net)”
     *  2。终止非关键的本地资源
     *     与对象的本地对等体(nativepeer)有关,它是一个本地对象(nativeobject),普通对象通过一个
     *   本地方法(nativemethod)委托给一个本地对象。因为本地对等体不是一个普通对象,所以GC不会知道它,
     *   当它的普通对等体被回收时,它不会被回收。在本地对等体并不拥有关键资源的前提下,那么该类应该具有
     *   一个显示的终止方法
     *另:既然使用了终结函数,那么要记住调用super.finalize();
     *最后:如果把一个finalizer与一个公有的非final类关联起来,请考虑使用终结函数守卫者(finalizerguardian,
     *     匿名类的单个实例),以确保即使子类的终结函数未能调用super.finalize(),该终结函数也会被执行
     */ 
}
//为每个将被终结的对象创建一个附加对象,然后吧终结函数放在一个匿名类中,该匿名类的唯一用途是终结其外围实例,
//该匿名类的每个单例就是终结函数守卫者,外围类的每一个实例都会创建这样一个守卫者。外围类的每个实例都会
//创建一个守卫者。外围实例在它的私有实例域中保存着一个对其守卫者的惟一引用,所以守卫者与外围实例可以同时启动终结过程。
//当守卫者被终结时,它执行外围实例所期望的终结行为,就好像它的终结函数时外围对象上的一个方法一样:

//终结函数守卫者示例
publicclass Foo{
       privatefinal Object finalizerGuardian = new Object(){
                 protectd void finalize() throws Throwable {
                          //Finalize outer Foo object 
                 }
       };
       //Remainder omitted
}

posted on 2008-04-22 18:54  wxf0701  阅读(528)  评论(0编辑  收藏  举报