【问题标题】:Order of the finalize() operations in JavaJava 中 finalize() 操作的顺序
【发布时间】:2017-11-07 10:18:14
【问题描述】:

我正在尝试了解有关 Java 垃圾收集器和 finalize() 方法的练习。

public class Five {
    static int x = 1;
    class String5 {
        String s;
        String5() {
            this.s = ""+(++x);
        }
        public void finalize() {
            System.out.print(s);
        }
    }

    String5 a = new String5();
    void f() {
        String5 a = new String5();
    }
    public void finalize() {
        System.out.print("H");
    }

    public static void main(String[] args) {
        Five a5 = new Five();
        a5.f();
        a5 = new Five();
        a5.f();
        System.gc();
        System.runFinalization();
    }
}

练习要求我预测输出。正确答案是532H。我预测输出应该是2H35,我不明白为什么我的排序不正确。

【问题讨论】:

    标签: java oop garbage-collection finalize


    【解决方案1】:

    根据 JLS,Java 语言没有定义finalize 方法的执行顺序,所以实际的顺序是一个实现细节。

    JLS 12.6. Finalization of Class Instances:

    Java 编程语言没有对 finalize 方法调用进行排序。终结器可以按任何顺序调用,甚至可以同时调用。

    您遇到的顺序似乎暗示了堆栈实现 - 符合垃圾回收条件的 String5 的第 4 个也是最后创建的实例首先完成(打印 5),然后是第 2 个和第 1 个(第 3 个)不符合垃圾回收条件)打印32,最后第一个Five 实例最终确定并打印H

    但是,不同的 JDK 实现可能会产生不同的顺序。

    【讨论】:

    • 哦...所以当我的老师要求正确的顺序时,问题中有缺陷吗?
    • @EdoardoMeneghini 根据 JLS 的说法,也许正确的答案是没有正确的顺序。
    • “不同的 JDK 实现可能产生不同的顺序”或根本不产生输出或不打印所有字符或令人惊讶地打印出比预期更多的字符。因为 a) 根本无法保证终结器运行,b) gc()runFinalization() 只是可能会被忽略的建议,但是 c) 垃圾收集/终结仍然可能运行没有这些提示,例如在程序中间和 d) 如果没有后续使用对象,即使被局部变量引用,对象也可能被收集,因此第二个 Five 实例也可能被收集。
    猜你喜欢
    • 1970-01-01
    • 2021-06-05
    • 2015-07-07
    • 2018-07-06
    • 2016-02-15
    • 2015-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多