PS:我确实知道如何正确清理,而不依赖于finalize()
。
Java不保证在程序退出时,会进行适当的垃圾收集吗?
E.g。假设我已经在缓存中保留了一些数据而不是频繁地序列化,我还实现了finalize()
,希望如果由于任何原因(崩溃除外)我的程序正常退出,那么缓存将被写入DB我的代码在finalize()方法中的/ file / some-storage。但是根据以下的小实验,似乎JVM没有“优雅地”清理内存,它只是退出。
Java spec(参见程序退出)说明了在退出时如何处理内存/ gc。或者我应该查看规范的不同部分吗?
在Windows 7上使用1.6.0.27 64位获取以下示例(最后输出)
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虚拟机假定没有特定类型的自动存储 管理系统和存储管理技术可以选择 根据实施者的系统要求.1虽然看起来如此 令人困惑的是,垃圾收集模型并不严格 定义实际上是重要且有用的 - 严格定义的垃圾 集合模型可能无法在所有平台上实现。 同样,它可能排除有用的优化并伤害 从长远来看平台的表现。
虽然没有一个地方包含完整的定义 所需的垃圾收集器行为,很多GC模型都是 通过Java语言中的许多部分隐式指定 规范和JVMS。虽然没有确切的保证 接下来的过程,所有兼容的虚拟机共享基本 本章描述的对象生命周期。
答案 1 :(得分:3)
见Runtime.runFinalizersOnExit()。请注意,它已弃用,请注意其余评论。我认为你可以合法地推断它默认是关闭的,但是你也应该注意它可以打开。