2011-10-24 39 views
11

PS:我知道如何正确清理,而不依赖于finalize()JVM/GC是否在程序/线程退出时调用`finalize()`?

Java不能保证程序退出时,垃圾回收会被正确执行吗?

E.g.可以说我已经将一些数据保存在缓存中,而不是频繁地序列化,我还实现了finalize(),希望如果由于任何原因(崩溃除外),我的程序将优雅地退出,那么缓存将写入DB /文件/某些我的代码在finalize()方法中存储。但根据以下的小实验,似乎JVM并没有“优雅地”清理内存,它只是退出。

Java spec(见程序退出)什么都不说ABT内存/ GC是如何退出处理。或者我应该看看规范的不同部分?

采取使用1.6.0.27 64位下面的例子中(在端输出),在Windows 7

public class Main { 

     // just so GC might feel there is something to free.. 
    private int[] intarr = new int[10000]; 

    public static void main(String[] args) { 
     System.out.println("entry"); 
     Main m = new Main(); 
     m.foo(); 
     m = new Main(); 
     // System.gc(); 
     m.foo(); 
     m = null; 
     // System.gc(); 
     System.out.println("before System.exit(0);"); 
     System.exit(0); 
    } 

    @Override 
    protected void finalize() throws Throwable { 
     System.out.println("finalize()"); 
     super.finalize(); 
    } 

    public void foo() { System.out.println("foo()"); } 
} 

/* 
* Prints: 
* entry 
* foo() 
* foo() 
* before System.exit(0); 
*/ 

变化:

  • 如果我去掉任一项System.gc()则没有finalize()被称为。
  • 如果我取消两个System.gc()的注释,则finalize()被调用两次。
  • 无论System.exit()被称为与否对finalize()是否被称为没有任何影响。
+0

你的问题是程序可能在任何时候都不正常地死去。您可能还需要能够在重新启动时进行清理。 –

回答

10

没有,Java不保证在程序退出的GC将触发。如果您想在退出时使用Runtime.addShutdownHook方法进行操作。阅读this Sun撰写的关于SPEC说的文章。

Java平台的规范对于 垃圾收集的实际工作原理做出了很少的承诺。以下是Java Virtual 机器规范(JVMS)关于内存管理的内容。

堆是在虚拟机启动时创建的。堆存储为 对象由自动存储管理系统(作为垃圾收集器知道 )回收;对象从不显式释放。 Java虚拟机不采用特定类型的自动存储管理系统,根据实现者的系统需求可以选择存储管理技术 。虽然看起来 令人困惑,但垃圾收集模型并非严格定义的实际上非常重要且有用 - 一个严格定义的垃圾收集模型可能不可能在所有平台上实现。 同样,它可能会妨碍有用的优化,并长期损害平台的性能。

虽然没有包含的 所需的垃圾收集器的行为的完整定义,许多GC模型是 隐含通过一些在Java语言规范 和JVMS部分没有指定任何一个地方。虽然没有关于确切的 过程的保证,但所有符合标准的虚拟机都共享本章中描述的基本的对象生命周期。

+0

它(例如规格)在任何地方都这么说吗? – Kashyap

+1

虽然您提供的描述仍然没有真正说明GC在退出时没有完成,但我认为已经充分表明它留给了JVMs impls ..感谢信息abt'addShutdownHooks()',不知道这一点。 – Kashyap

+1

在规范中没有否定“GC不一定在退出时运行”的负面声明。规范中的故意模棱两可和我引用的广泛陈述都是陈述的。 –

3

请参阅Runtime.runFinalizersOnExit()。请注意,它已被弃用,并注意其余的评论。我认为你可以合理地推断它是默认关闭的,但你也应该注意它可以打开。

相关问题