Java并手动执行finalize

Ike*_*nez 16 java garbage-collection finalize

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

这将是一个近似的例子:

MyObject m = new MyObject();

m.finalize();

m = null;

System.gc()
Run Code Online (Sandbox Code Playgroud)

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

Out*_*mer 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");
}
Run Code Online (Sandbox Code Playgroud)

输出是:

开始
敲定!
定稿!
DONE

那里的每一个资源都表示永远不会明确地调用finalize(),甚至几乎都没有实现该方法,因为无法确定是否以及何时调用它.你最好手动关闭所有资源.


小智 7

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

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

报价:"finalize方法被调用的对象后,没有采取进一步的行动,直到Java虚拟机再次确定不再有通过这个对象可以通过尚未终止的任何线程访问的任何手段,包括可以最终确定的其他对象或类的可能动作,此时可以丢弃该对象."来自Java API Doc,java.Object.finalize();

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