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