Java和手动执行finalize

18

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

以下是一个近似的例子:

MyObject m = new MyObject();

m.finalize();

m = null;

System.gc()

明确调用finalize()方法会使得JVM的垃圾回收器不运行对象mfinalize()方法吗?

3个回答

30
根据这个简单的测试程序,即使您明确调用 finalize() 方法,JVM 仍会进行其调用:
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()方法,而且通常甚至不要实现该方法,因为无法保证它何时会被调用。最好手动关闭所有资源。

7
了解垃圾回收(GC)的工作流程是理解finalize功能的前提。调用.finalize()不会触发垃圾回收,也不会调用system.gc。实际上,finalize方法帮助程序员将对象的引用声明为“未引用”。
GC会强制暂停JVM的运行操作,这会对性能造成影响。在操作期间,GC将遍历所有引用的对象,从根对象(即main方法调用)开始。通过手动将对象声明为未引用,可以减少此暂停时间,因为它将削减自动运行时声明对象引用过时的操作成本。通过声明finalize(),程序员将对象的引用设置为过时,因此在下一次GC操作运行时,GC运行将在不使用操作时间的情况下扫描对象。
引用Java API文档中java.Object.finalize()的内容:“在为对象调用finalize方法之后,直到Java虚拟机再次确定没有任何方式可以让任何尚未死亡的线程访问该对象,包括其他对象或类可能采取的操作以及准备完成的类,此时该对象可能被丢弃。”
有关详细说明,您还可以查看:javabook.computerware

2

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

public void cleanUp() {
  .
  .
  .
}

myInstance.cleanUp();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接