GC会走多远

Esp*_*pen 3 java garbage-collection

Java GC会走多远?让我说我有这个代码:

public class MyClass {
    private Object myObject = new Object();
    public void clear() {
        myObject = null;
    }
}

public class MyMain {
    ...
    MyClass myClass = new MyClass();
    ...
    myClass.clear();
    myClass = null;
}
Run Code Online (Sandbox Code Playgroud)

在将myClass设置为null之前,是否需要调用myClass.clear()以确定GC是否会删除myClass中的myObject?或者将myClass设置为null并且GC将删除所有嵌套对象是否足够?

也许我有点偏执,答案就像"GC最终将删除任何正在运行的代码或任何未来可用代码无法访问的任何对象"一样简单.因此,如果创建的对象不可用,或者永远不可用,在任何正在运行的代码中,它最终会成为GC的受害者,即使它被嵌套并使C++程序员感到害怕?

Jon*_*eet 9

不,你不需要打电话myClass.clear().当无法通过实时引用到达对象时,它将有资格进行垃圾回收.这并不意味着它会被立即收集,但它将有资格收集.

这是非常罕见适当设置为空引用进行垃圾回收的缘故-它伤害你的代码的可读性这样做.当然也有例外 - 例如,ArrayList<T>将内部缓冲区的一个元素设置为null不再需要它时,以避免意外阻止对象被垃圾收集 - 但通常对象中的字段是有效的,只要对象本身是必需的就有用.简而言之,我几乎从不一个像这样的方法MyClass.clear(),更不用说了.

将局部变量设置为null也很少值得.您的代码MyMain不清楚,因为它在方法之外无效...如果您将所有代码都放在方法中,那么您也不需要设置myClass为null.当方法完成时,变量将不再作为它所引用的对象的GC根目录 - 当然,如果存在其他 GC根,则该对象仍然不符合垃圾收集的条件.但是,在方法结束时将局部变量设置为null是没有意义的.


Mat*_*all 8

不需要任何内容设置为null以使其成为GC.不要偏执.

不要尝试像C++一样编写Java.

  • @Byron:不,强调*不*.如果您的评论是一个答案,我会对它进行投票.首先,对象不会超出范围 - 变量可以.有很大的不同.其次,在特定变量超出范围之后,对象可能*符合*用于垃圾收集,但这并不意味着它将在该点收集. (10认同)
  • 是的,当它超出范围时它将是GC'd. (2认同)
  • 那么,*有*值得将变量设置为null的场合.例如,想象一下,如果`ArrayList <T>`在删除元素并且其余部分向下移动后,在其后备数组中左侧引用 - 这将导致从GC的角度可以访问对象,即使实际上没有办法访问它们. (2认同)

Eya*_*der 7

通过引用归零来"帮助"gc很少真正需要.

这是一个人工案例,其中归零有助于:

    long[] arr = new long[7000000];
    //arr = null;
    arr = new long[7000000];
Run Code Online (Sandbox Code Playgroud)

如果使用-Xmx100M运行它,它将因OutOfMemoryError而失败.如果取消注释使arr为null的行,它将正常工作.发生这种情况是因为arr引用仍在保留巨大的数组,而另一个正在创建.内存分配在赋值之前发生,它触发垃圾收集,并且失败.在使引用归零时,GC成功创建足够的空间.