假设我已经创建了一些带有 close() 方法的资源类来清理资源,并且如果有人忘记调用 close(),我想重写 Finalize() 来释放资源(并打印警告)。如何正确地做到这一点?
- 是否仅建议用于本机(JNI 分配)资源?
- 如果您使用终结器对另一个已终结的对象的引用,会发生什么情况?如果存在循环依赖,我不知道垃圾收集器如何阻止您访问其终结器可能已执行的对象。
- 是否有更好的替代方案来覆盖 Finalize() 来检测和/或处理资源泄漏?
- 实现终结器时还有其他需要注意的陷阱吗?
注意:我知道使用 Finalize() 通常是个坏主意,并且不能保证它会被调用,还有其他几个问题正在讨论这一点。这个问题具体是关于how在 Java 中实现终结器,而不是关于why你应该(或不应该)。
In 有效的java(第二版) https://rads.stackoverflow.com/amzn/click/com/0321356683,Joshua 在第 7 条中详细介绍了如何做到这一点。他首先建议你几乎不应该使用finalizer
s。然而,使用它来仅打印一条日志语句以表明存在资源泄漏的原因之一。他说这样做的缺点之一是有人可以扩展你的类而不正确调用超级终结器。所以他建议在子类中做这样的事情:
// 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 可能会选择在将来的某个时间运行它。如果您依赖此方法来进行提交或做一些重要的事情,那么这是一个坏主意。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)