我的JDK版本是1.7.0_25
class A {
public void finalize() {
System.out.println("deleting...");
}
}
public class Test {
public static void main(String[] args) {
new A();
System.gc();
System.out.println("main class");
}
}
我预计输出为
deleting...
main class
但在我的情况下没有输出是什么原因?当我使用JDK 1.7.0_09在线编译和运行代码时,输出为,
main class
deleting...
为什么“主要类”首先打印?
答案 0 :(得分:1)
GC从不保证何时进行清理,
finalize()
可能会或可能不会被召唤。
通过doin System.gc();
,您只是要求调用GC,而是由JVM来完成您的请求。
Will the System.gc() invoke the cleanup?
答案取决于很多因素,例如您正在运行的JVM,它所处的模式以及它使用的垃圾收集算法。
我不会在你的代码中依赖它。如果JVM即将抛出OutOfMemoryError,则调用System.gc()不会停止它,因为垃圾收集器会在它进入极端之前尝试尽可能多地释放它。
所以...如果有什么想要肯定执行的,请不要在finalize()
答案 1 :(得分:1)
最终确定时未指定。指定/保证的 only 事物是在从堆中实际删除可终结对象之前完成最终化。
实际上,终结通常由特殊的终结线程完成,该线程在主GC线程完成其工作时得到通知。看起来控件在终结线程处理对象之前返回主线程。
基本上,你不能依赖这些事情发生的顺序。这就是为什么依靠最终确定来做事情的原因之一通常是一个坏主意。
此外,甚至不能保证System.gc()
电话会做任何事情。
简而言之,您所观察到的是“在最终确定的指定行为的”范围内“。垃圾收集器正在工作。这是你的期望不正确。
答案 2 :(得分:1)
当您调用System.gc()
方法时,无法保证是否会调用finalize()方法。去throgh java API。对于第二个问题,main()方法是一个线程。当你调用垃圾收集器时,它将在另一个线程中执行。所以如果你理解了线程,那么现在你就会知道答案(你无法预测线程执行顺序)
答案 3 :(得分:1)
其他答案正确地说明没有办法确保终结器运行。我只想提出一些关于执行顺序的问题:
当GC检测到具有finalize()
的对象 - 要删除的方法时,它不会立即删除它,而是首先将其放在终结队列中。在GC完成并且应用程序恢复工作之后,VM将开始运行所有排队的终结器 - 这应该解释输出的顺序。只有在那之后才能实际对象进行GC。