我正在阅读java章节中有关垃圾收集器的想法,我发现了一个运行一次的例子。但我无法弄清楚为什么。
public class Book {
boolean checkedOut = false;
Book(boolean checkOut) {
checkedOut = checkOut;
}
void checkIn() {
checkedOut = false;
}
@Override
protected void finalize() {
if (checkedOut) {
System.out.println("Error: checked out");
}
// Normally, you’ll also do this:
//super.finalize(); // Call the base-class version
}
public static void main(String[] args) {
Book novel = new Book(true);
// Proper cleanup:
novel.checkIn();
// Drop the reference, forget to clean up:
new Book(true);
// Force garbage collection & finalization:
System.gc();
}
}
即使内存没有用完,对System.gc()
的调用也会强制终止对象。
为什么程序输出错误:检出只能在连续执行4-5之后?我不能明白这一点,你能试着澄清一下吗? 我希望每次调用GC时都会执行finalize方法,因此每次都应该提示检出错误。
由于
答案 0 :(得分:3)
您是否阅读过文档?
来自http://docs.oracle.com/javase/7/docs/api/java/lang/System.html#gc%28%29
调用gc方法建议 Java虚拟机花费大量精力来回收未使用的对象,以使其当前占用的内存可用于快速重用。当控制从方法调用返回时,Java虚拟机已经尽力从所有丢弃的对象中回收空间。
(强调我的)
它没有说“在此次调用之后,您可以保证所有无根对象都将被回收并且它们的终结器被执行”。你给GC一个建议,看看是否有任何数据可以回收,这是个好主意。仅此而已。
(另外,http://docs.oracle.com/javase/7/docs/api/java/lang/System.html#runFinalization%28%29可能更适合您实际需要发生的事情,因为您向我们展示的代码会检查对象的终结器是否已执行,而不是对象是否已执行已被垃圾收集)
答案 1 :(得分:1)
对象永远不会被垃圾收集(因此永远不会调用finalize
)。
如果对象永远不符合gc 的条件(因为它可以通过 JVM的整个生命周期 )或者当没有垃圾收集实际上在对象符合条件的时间和JVM停止运行的时间之间运行(这通常发生在简单的测试程序)。
无法保证finalize()
将被调用。
注意: 如果您是出于理解目的而这样做,那么它很好,但您应该避免明确调用System.gc()
。
免责声明:我并不是说这是一种正确的做法。我只是试着想一想,如果在延迟调用之前有一些延迟,那么创建的对象可能会被gc检测到并且每次都会被收集。
替代方法(不保证可以正常工作)
Thread.sleep(10000); //try sleeping for a while before giving a call to gc
// Force garbage collection & finalization:
System.gc();
在我的环境中连续4次打印所需的输出。