18

如果我finalize()从我的程序代码中调用一个对象,当垃圾收集器处理这个对象时,JVM是否还会再次运行该方法?

这将是一个近似的例子:

MyObject m = new MyObject();

m.finalize();

m = null;

System.gc()

是否会显式调用finalize()使JVM的垃圾收集器不在finalize()对象上运行该方法m

4

3 回答 3

30

根据这个简单的测试程序,即使你显式调用了 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() ,甚至几乎永远不会实现该方法,因为无法保证是否以及何时调用它。您最好手动关闭所有资源。

于 2008-08-26T19:23:06.483 回答
7

必须了解垃圾收集器(GC)工作流程才能了解 finalize 的功能。调用 .finalize() 不会调用垃圾收集器,也不会调用 system.gc。实际上,finalize 将帮助编码人员将对象的引用声明为“未引用”。

GC 会强制暂停 JVM 的运行操作,这会降低性能。在运行过程中,GC 会遍历所有引用的对象,从根对象(你的主方法调用)开始。可以通过手动将对象声明为未引用来减少此暂停时间,因为它会降低通过自动运行声明对象引用已过时的操作成本。通过声明 finalize(),coder 将对象的引用设置为过时,因此在下一次运行 GC 操作时,GC 运行将在不使用操作时间的情况下扫描对象。

引用:“在为一个对象调用了 finalize 方法之后,在 Java 虚拟机再次确定没有任何方法可以让任何尚未终止的线程访问该对象之前,不会采取进一步的行动,包括准备完成的其他对象或类的可能操作,此时该对象可能被丢弃。”来自 java.Object.finalize() 上的 Java API Doc;

详细解释也可以查看:javabook.computerware

于 2013-12-20T15:22:18.623 回答
2

JVM 不会为任何给定对象多次调用 finalize 方法。无论如何,您都不应该依赖 finalize,因为不能保证它会被调用。如果您因为需要执行清理代码而调用 finalize,那么最好将其放入单独的方法中并使其显式,例如:

public void cleanUp() {
  .
  .
  .
}

myInstance.cleanUp();
于 2008-08-26T18:59:31.907 回答