Java和手动执行finalize
-
09-06-2019 - |
题
如果我打电话 finalize()
在我的程序代码中的一个对象上, 虚拟机 当垃圾收集器处理这个对象时仍然再次运行该方法吗?
这是一个大概的例子:
MyObject m = new MyObject();
m.finalize();
m = null;
System.gc()
是否会显式调用 finalize()
使 虚拟机的垃圾收集器不运行 finalize()
对象上的方法 m
?
解决方案
根据这个简单的测试程序,即使您显式调用它,JVM 仍然会调用 Finalize():
private static class Blah
{
public void finalize() { System.out.println("finalizing!"); }
}
private static void f() throws Throwable
{
Blah blah = new Blah();
blah.finalize();
}
public static void main(String[] args) throws Throwable
{
System.out.println("start");
f();
System.gc();
System.out.println("done");
}
输出是:
开始
敲定!
敲定!
完毕
那里的每个资源都说永远不要显式调用 Finalize(),而且几乎永远不要实现该方法,因为无法保证是否以及何时调用它。您最好手动关闭所有资源。
其他提示
要理解finalize的功能,就必须了解垃圾收集器(GC)工作流程。调用 .finalize() 不会调用垃圾收集器,也不会调用 system.gc。实际上,finalize 对编码器有帮助的是将对象的引用声明为“未引用”。
GC 会强制暂停 JVM 的运行,从而降低性能。在运行过程中,GC会从根对象(你的main方法调用)开始遍历所有引用的对象。可以通过手动将对象声明为未引用来减少此挂起时间,因为它将减少通过自动运行来声明对象引用已过时的操作成本。通过声明finalize(),编码器将对象的引用设置为废弃,因此在下一次运行GC操作时,GC运行将在不使用操作时间的情况下扫描对象。
引用:“对一个对象调用finalize方法后,不会采取进一步的操作,直到Java虚拟机再次确定任何尚未死亡的线程不再可以通过任何方式访问该对象,包括可能的情况。”其他对象或类的操作已准备好完成,此时该对象可能会被丢弃。“来自 Java API 文档中的 java.Object.finalize();
详细解释,您还可以查看: javabook.computerware
对于任何给定的对象,JVM 永远不会多次调用 Finalize 方法。无论如何,您不应该依赖于 Finalize,因为不能保证它会被调用。如果您调用 Finalize 是因为需要执行清理代码,那么最好将其放入单独的方法中并使其明确,例如:
public void cleanUp() {
.
.
.
}
myInstance.cleanUp();