《Thinking in Java, 4th Edition》中的finalize方法

3

我正在阅读《Java编程思想》第四版。我发现一个问题:当我在Eclipse IDE中测试源代码时,结果不同。希望有人能帮助我!

以下是源代码:

class Book {
    boolean checkedOut = false;

    Book(boolean checkOut) {
        checkedOut = checkOut;
    }

    void checkIn() {
        checkedOut = false;
    }

    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 class TerminationCondition {
    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);
        new Book(true);
        new Book(true);

        //Force garbage collection & finalization:
        System.gc();
    }
}

书的结果:

Error: Checked out

The result of IDE

(nothing)

我使用的Java版本:

Java版本“1.7.0_51”
Java(TM) SE运行时环境(版本1.7.0_51-b13)
Java HotSpot(TM) 64位服务器虚拟机(版本24.51-b03,混合模式)

书中所述的Java版本是Java 5。finalize方法是否有变化?


4
不能保证 1:System.gc 会触发垃圾回收,2:finalize 方法一定会被调用。有可能 JVM 终止阻止了 gc 正常释放对象...或者其他原因。 - MadProgrammer
3个回答

1
JVM有自己的垃圾回收管理策略,即使您单独调用finalize()或不调用! JVM会进行最优化处理,用户不需要干预内存清理过程。因此,您观察到的与Java版本或其他任何事情都无关!它完全取决于JVM及其自动内存管理策略。

0

你的主线程在GC运行之前退出了。因此,你没有得到任何输出。请在你的主方法中进行以下更改,你就会看到输出:

System.gc();
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

0
这本书中 Java 的版本是 Java 5。finalize 方法是否发生了什么变化?
如果你阅读 System.gc() 相关的规范,你会发现几乎没有任何保证会发生什么:
  1. 不能保证调用 System.gc() 会导致任何事情发生。真的。

  2. 不能保证所有垃圾都将被收集。

  3. 不保证垃圾对象将被终止...尽管有 finalize() 方法。

这里的真正问题是你正在查看的示例做出了“无法保证的假设”。它在早期版本的 Java 中运行良好。它在更近期的版本中不起作用...之类的。它只是一个糟糕的示例。

但这确实(我希望)向您证明,依赖于可预测的时间调用finalize方法是不明智的。事实上,最好不要将finalize用于除“系带和扣子”整理代码之外的任何东西。


实际上,finalization通常发生在垃圾收集器完成之后。(它是由一个名为“finalization线程”的守护程序执行的,该线程通过所有已被识别为不可达和需要finalization的对象,并进行处理。)因此,在您的示例中可能发生的情况是JVM在GG运行后退出,但在finalization线程有机会处理可终止对象之前。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接