比方说,我已经创造了一些资源类的清理资源close()方法,我想重写的finalize()以释放资源(并打印警告)如果有人忘记调用close()。 这可怎么得当?
- 难道只推荐用于本地(JNI分配)的资源?
- 如果你使用到已经敲定另一个对象的引用,从一个终结,会发生什么? 如果有循环依赖,我没有看到垃圾收集器如何阻止您访问对象,它们的终结可能已经执行。
- 是否有没有更好的方法来覆盖的finalize(),用于检测和/或处理资源泄漏?
- 任何其他陷阱要注意执行终结的时候?
注:我知道,使用敲定()通常是坏主意,而且它不能保证被调用,也有讨论这个其他的几个问题。 这个问题是特别了解如何在Java中实现一个终结,不是为什么你应该(或者不应该)。
在有效的Java(第2版) ,约书亚就转至编号7的细节你如何能做到这一点。 他首先建议你应该几乎从来不使用finalizer
秒。 然而,一个理由去使用它仅打印日志声明说您有一个资源泄漏。 他说,平局背对着做这种方式是,有人可以扩展你的类并不能正确调用父类的终结之一。 因此,他建议做这样的事情在子类:
// Manual finalizer chaining
@Override protected void finalize() throws Throwable {
try {
... // Finalize subclass state
} finally {
super.finalize();
}
}
这是为了确保,如果事情在当前类打破了finally
还是会被调用。 这可能是一个坏的解决方案,因为它取决于谁是继承类的人。 另一种解决方案是使用一个守护对象文件完成这件事。 这看起来像:
// Finalizer Guardian idiom
public class Foo {
// Sole purpose of this object is to finalize outer Foo object
private final Object finalizerGuardian = new Object() {
@Override protected void finalize() throws Throwable {
... // Finalize outer Foo object
}
};
... // Remainder omitted
}
这是一个更简洁的方法,因为你知道,没有人可以覆盖该功能。
建议的方式来关闭资源依然贯彻Closeable
,并确保它是由用户关闭。 作为Josuha建议,你不应该在做任何时间敏感操作finalize
方法。 该JVM可以选择在未来某个时候作为运行它。 如果你根据这个方法做的提交或一些重要的事情,然后这是一个坏主意。
难道只推荐用于本地(JNI分配)的资源?
不可以。您的使用情况也是终结一个有效的。 我的意思是记录资源泄漏。
如果你访问已经敲定另一个Java对象,在终结会发生什么?
如果您仍然可以访问它,它没有最终确定。 或者,也许我失去了你的问题的东西。
我现在知道了。 这可能是A和B都符合垃圾收集和他们之间有一个参考的情况下。 它应该是没有问题,因为默认情况下finalize()
什么都不做。 如果你写为您的自定义对象finalize()
方法,你应该写你的代码独立的,他们最终确定的顺序。 你也应该警惕为基准成为null
与相应的对象可能已经被垃圾收集。
是否有没有更好的方法来覆盖的finalize(),用于检测和/或处理资源泄漏?
我使用终结时,检测和记录/警告对泄漏不处理它认为最重要的事情。 并记录这种泄漏的最佳时刻是之前的资源对象进行垃圾回收。 因此终结是一个天生适合这个。
我想强调这一点:我不会用终结处理程序员是忘了关资源,而是要告诉他,他需要修复他的代码。
任何其他陷阱要注意执行终结的时候?
这似乎也有与具有终结对象的性能损失。 你应该做一个测试看它是如何为您服务。 如果有一个重要的性能损失,我会试着去想像一个机制,使用终结只是在开发时登录资源泄漏。
而继承与终结的对象时,由阿米尔Raminfar的建议照顾。
一两件事:看一看的[源代码FileInputStream][1]
或[FileOutputStream][2]
他们使用终结出于同样的原因。