垃圾收集详细信息:此对象是否符合GC的条件?

aio*_*obe 8 java garbage-collection

我想这样的程序......

class Test {
    public static void main(String[] args) {
        new Test();
        System.out.println("done");
    }

    protected void finalize() {
        System.out.println("this object is known to never be referenced.");
    }
}
Run Code Online (Sandbox Code Playgroud)

...可能"this object is known to never be referenced."之前输出"done".(如果我错了,请纠正我!)

此外,编译器/ JVM很容易检测到"未读的本地人".例如,在下面的程序中,Eclipse注意到" 永远不会读取局部变量t ".

但是,"this object is known to never be referenced.""done"给出下面程序的(.class版本)之前,JVM输出是否合法?

class Test {
    public static void main(String[] args) {
        Test t = new Test();
        System.out.println("done");
    }

    protected void finalize() {
        System.out.println("this object is known to never be referenced.");
    }
}
Run Code Online (Sandbox Code Playgroud)

大多数垃圾收集文档都谈到了可达性.鉴于t从未读过的事实,该对象显然不是"可达"的,或者?

欢迎参考JLS.

650*_*502 5

Java语言规范的12.6.1中说:

12.6.1实施最终确定

每个对象都可以通过两个属性来表征:它可以是可达的,终结器可达的或不可达的,并且它也可以是未终结的,可终结的或最终的.可到达对象是可以从任何活动线程的任何潜在继续计算中访问的任何对象.可以设计优化程序的转换,以减少可达到的对象的数量,使其少于可以被认为可达的对象的数量.

例如,编译器或代码生成器可以选择设置将不再用于null的变量或参数,以使得此类对象的存储可能更快地被回收.

在我看来,最后一句话恰好涵盖了你所询问的案例.t可以null在范围结束之前隐式设置变量,从而使对象无法访问.

这在C++中会是一场灾难,因为很多代码依赖于范围结束时的精确破坏时间(例如锁定).