简体   繁体   English

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

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

I suppose that a program like this... 我想这样的程序......

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

...may possibly output "this object is known to never be referenced." ...可能会输出"this object is known to never be referenced." before "done" . "done"之前。 (Correct me if I'm wrong here!) (如果我错了,请纠正我!)

Furthermore, it is easy for a compiler/JVM to detect "unread locals". 此外,编译器/ JVM很容易检测到“未读的本地人”。 In the program below for instance, Eclipse notices that " The local variable t is never read ". 例如,在下面的程序中,Eclipse注意到“ 永远不会读取局部变量t ”。

However would it be illegal for the JVM to output "this object is known to never be referenced." 但是, 如果JVM输出"this object is known to never be referenced."那么这是非法的"this object is known to never be referenced." before "done" given the (.class version) of the program below? "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.");
    }
}

Most documentation of garbage collection talk about reachability. 大多数垃圾收集文档都谈到了可达性。 Given the fact that t is never read, the object is obviously not "reachable", or? 鉴于t永远不会被读取,对象显然不是“可达”的,或者?

References to the JLS are appreciated. 欢迎参考JLS。

In 12.6.1 of the Java Language Specification says: Java语言规范的12.6.1中说:

12.6.1 Implementing Finalization 12.6.1实施最终确定

Every object can be characterized by two attributes: it may be reachable, finalizer- reachable, or unreachable, and it may also be unfinalized, finalizable, or finalized. 每个对象都可以通过两个属性来表征:它可以是可达的,终结器可达的或不可达的,并且它也可以是未终结的,可终结的或最终的。 A reachable object is any object that can be accessed in any potential continuing computation from any live thread. 可到达对象是可以从任何活动线程的任何潜在继续计算中访问的任何对象。 Optimizing transformations of a program can be designed that reduce the number of objects that are reachable to be less than those which would naively be considered reachable. 可以设计优化程序的转换,以减少可达到的对象的数量,使其少于可以被认为可达的对象的数量。

For example, a compiler or code generator may choose to set a variable or parameter that will no longer be used to null to cause the storage for such an object to be potentially reclaimable sooner. 例如,编译器或代码生成器可以选择设置将不再用于null的变量或参数,以使得此类对象的存储可能更快地被回收。

The last phrase seems to me covering exactly the case you are asking about. 在我看来,最后一句话恰好涵盖了你所询问的案例。 The variable t can be set to null implicitly before the end of the scope, therefore making the object unreachable. 变量t可以在作用域结束之前隐式设置为null ,从而使对象无法访问。

This in C++ would be a disaster because a lot of code depends on exact destruction timing at the end of scope (eg for locks). 这在C ++中会是一场灾难,因为很多代码依赖于范围结束时的精确破坏时间(例如锁定)。

...may possibly output "this object is known to never be referenced." ...可能会输出“此对象已知永远不会被引用”。 before "done". 在“完成”之前。

There are three possible behaviors: 有三种可能的行为:

  • the message is output before "done", 消息在“完成”之前输出,

  • the message is output after "done", 在“完成”之后输出消息,

  • the "this object is known to never be referenced" message is not output at all. “此对象已知永远不会被引用”消息根本不输出。

(In practice, the most likely behavior is that the last one. In fact, it is a virtual certainty unless you generate lots of garbage between creating the Test instance and printing "done".) (实际上,最可能的行为是最后一个。事实上,除非你在创建Test实例和打印“done”之间产生大量垃圾,否则这是一个虚拟的确定性。)

However would it be illegal for the JVM to output "this object is known to never be referenced." 但是,如果JVM输出“已知此对象永远不会被引用”,那么这是非法的。 before "done" given the (.class version) of the program below? 在“完成”之前给出下面程序的(.class版本)?

No it would not be illegal. 不,这不是非法的。 The Test instance cannot "be accessed in any potential continuing computation from any live thread" , and is therefore unreachable. Test实例不能“在任何可能的连续计算中从任何活动线程访问” ,因此无法访问。 Therefore it would be legal for the JVM to garbage collect it and finalize it immediately. 因此,JVM垃圾收集并立即完成它是合法的。

However, three events that must happen for the message to appear: 但是,要显示消息必须发生三个事件:

  • the GC has to run, GC必须运行,
  • the GC has to detect the object as unreachable, and GC必须将对象检测为无法访问,并且
  • the GC has to finalize the object. GC必须完成对象。

There is no guarantee that all of these events will happen before the application exits, yet alone in the window between creating the instance and printing "done". 不能保证所有这些事件都会在应用程序退出之前发生,而是在创建实例和打印“完成”之间的窗口中单独进行。


The bottom line is that you should never depend on finalization occurring in a Java application. 最重要的是,您永远不应该依赖于Java应用程序中的最终化。

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

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