Java 和手动执行完成

2022-09-02 20:05:45

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

这是一个近似的例子:

MyObject m = new MyObject();

m.finalize();

m = null;

System.gc()

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


答案 1

根据这个简单的测试程序,即使您显式调用了它,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");
}

输出为:

开始
定稿!
敲定!

每个资源都说永远不要显式调用finize(),甚至几乎从不实现该方法,因为无法保证是否以及何时调用它。您最好手动关闭所有资源。


答案 2

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

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

引用:“在为对象调用了 finalize 方法之后,在 Java 虚拟机再次确定不再有任何方法可以由任何尚未死亡的线程访问此对象之前,不会执行进一步的操作,包括其他对象或类可能执行的操作,这些对象或类已准备好完成, 此时,对象可能会被丢弃。“来自 Java API Doc on java。Object.finalize();

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