Java 垃圾收集详细信息:此对象符合GC条件吗?

Java 垃圾收集详细信息:此对象符合GC条件吗?,java,garbage-collection,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."); } } …可能

我想像这样的程序

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.");
    }
}
…可能会输出
“已知此对象从未被引用过。”
“完成”
之前。(如果我错了,请纠正我!)

此外,编译器/JVM很容易检测到“未读局部变量”。例如,在下面的程序中,Eclipse注意到“从未读取局部变量t”

但是如果JVM输出
“已知此对象从未被引用过。”
“完成”
之前,给定以下程序的(.class版本),这是否是非法的?

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.");
    }
}
大多数垃圾收集文档都讨论可达性。鉴于
t
从未被读取,对象显然无法“访问”,或者

请参考JLS。

中的说明:

12.6.1实施最终定稿

每个物体都有两个特征 属性:它可能是可访问的, 终结器-可访问或不可访问, 而且它也可能是未完成的, 可定稿的,可定稿的。可达的 对象是任何可以 在任何可能的情况下访问 从任何活动线程进行计算。 优化一个函数的变换 程序可以设计为减少 要删除的对象数 可到达的小于那些 会天真地被认为是可达的

例如,编译器或代码 生成器可以选择设置变量 或将不再使用的参数 用于null以导致存储为 这样一个对象可能是 可以更快地回收

在我看来,最后一句话似乎完全涵盖了你所问的情况。变量
t
可以在作用域结束之前隐式设置为
null
,从而使对象无法访问

<>这在C++中会是一个灾难,因为很多代码取决于范围结束时的精确销毁定时(例如对于锁)。 …可能会在“完成”之前输出“已知此对象从未被引用”

有三种可能的行为:

  • 消息在“完成”之前输出

  • 消息在“完成”之后输出

  • “已知此对象从未被引用”消息根本不会输出

(实际上,最有可能的行为是最后一个。事实上,除非在创建
Test
实例和打印“done”之间产生大量垃圾,否则这是一个虚拟的确定性行为。)

但是,在给定以下程序的(.class版本)的“完成”之前,JVM输出“已知此对象从未被引用”是否非法

不,这并不违法。
Test
实例无法“在任何活动线程的任何潜在连续计算中访问”,因此无法访问。因此,JVM对其进行垃圾收集并立即完成是合法的

但是,要显示消息,必须发生三个事件:

  • GC必须运行
  • GC必须将对象检测为不可访问,并且
  • GC必须完成对象
无法保证所有这些事件都会在应用程序退出之前发生,但只能在创建实例和打印“完成”之间的窗口中发生



底线是,您永远不应该依赖于Java应用程序中发生的终结。

至少在C#/.net中是这样。即使在第二个程序中,对象的终结也可能发生在“完成”消息之前。这是因为抖动可以自由地优化变量,一旦它明确不再被访问。啊哈,很有趣。也许Java也是如此。不过我目前还不确定。嗯,在Java.Yep中似乎是类似的。完全正确好发现。谢谢!对谢谢我知道“根本没有输出”。这就是我测试它时所发生的情况:-)这就是为什么我将它表述为“JVM……这是否是非法的……”aioobe回答,我相信。啊,是的。有了JLS的报价,事实上非常清楚!再次感谢。我已经很久没用Java了。。。但在当时,由于所有程序只是将计算机置于垃圾模式,GC显然从未找到对象:-D@6502-那是什么版本的Java?如果你说的是Java1.0,它在1997年就被淘汰了。