Java并手动执行finalize

时间:2008-08-26 18:51:42

标签: java garbage-collection finalize

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

这是一个近似的例子:

MyObject m = new MyObject();

m.finalize();

m = null;

System.gc()

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

3 个答案:

答案 0 :(得分:29)

根据这个简单的测试程序,即使你明确地调用它,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(),甚至几乎都没有实现该方法,因为无法确定是否以及何时调用它。你最好手动关闭所有资源。

答案 1 :(得分:7)

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

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

引用:“在为一个对象调用了finalize方法之后,在Java虚拟机再次确定不再有任何方法可以被任何没有的任何线程访问之前,不会采取进一步的操作。但是已经死了,包括其他可以最终确定的对象或类的可能动作,此时对象可能会被丢弃。“来自Java API Doc,java.Object.finalize();

有关详细说明,您还可以查看:javabook.computerware

答案 2 :(得分:1)

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

public void cleanUp() {
  .
  .
  .
}

myInstance.cleanUp();