繁体   English   中英

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

[英]Garbage Collection Details: Is this object eligible for GC?

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

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.");
    }
}

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

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

但是, 如果JVM输出"this object is known to never be referenced."那么这是非法的"this object is known to never be referenced." "done"之前给出下面程序的(.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。

Java语言规范的12.6.1中说:

12.6.1实施最终确定

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

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

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

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

...可能会输出“此对象已知永远不会被引用”。 在“完成”之前。

有三种可能的行为:

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

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

  • “此对象已知永远不会被引用”消息根本不输出。

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

但是,如果JVM输出“已知此对象永远不会被引用”,那么这是非法的。 在“完成”之前给出下面程序的(.class版本)?

不,这不是非法的。 Test实例不能“在任何可能的连续计算中从任何活动线程访问” ,因此无法访问。 因此,JVM垃圾收集并立即完成它是合法的。

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

  • GC必须运行,
  • GC必须将对象检测为无法访问,并且
  • GC必须完成对象。

不能保证所有这些事件都会在应用程序退出之前发生,而是在创建实例和打印“完成”之间的窗口中单独进行。


最重要的是,您永远不应该依赖于Java应用程序中的最终化。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM