Java GC将走多远

Java GC将走多远,java,garbage-collection,Java,Garbage Collection,JavaGC将走多远?假设我有以下代码: public class MyClass { private Object myObject = new Object(); public void clear() { myObject = null; } } public class MyMain { ... MyClass myClass = new MyClass(); ... myClass.clear(); my

JavaGC将走多远?假设我有以下代码:

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

public class MyMain {
    ...
    MyClass myClass = new MyClass();
    ...
    myClass.clear();
    myClass = null;
}
在将myClass设置为null之前,是否需要调用myClass.clear(),以确保GC将删除myClass中的myObject?或者将myClass设置为null,GC将删除所有嵌套对象就足够了吗


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

< P> GC最终将正确地处理对象。我觉得你可能有点太偏执了。尽管将对象设置为null并没有什么坏处

为了回答您的问题,如果您调用了myObject.clear,myObject=null,那么就没有理由再次将其重置为null。

您不需要将任何内容设置为null,就可以对其进行GC。不要妄想


<>不要尝试像C++那样编程java。< /p> < P>不,你不需要先调用<代码>清除< /代码>。GC将很高兴地找到未使用的
myObject
引用并回收它

事实上,GC可以处理相当复杂的对象图,包括循环引用:

public class Foo
{
    public HashMap a;
    public HashMap b;

    public Foo() {
        a = new HashMap();
        b = new HashMap();
        a.put("b", b);
        b.put("a", a);
    }
}
// ...
public void someFunction() {
   Foo f = new Foo();
}
(我通常不会把
a
b
公之于众,但我在这里尽量表现得极端保守。)

您不必清除
f
,或
a
,或
b
。如果没有任何内容引用
f
,最终将检查
f
的可达性,并且GC不会对
a
b
相互引用这一事实产生问题


中的详细信息(很多很多详细信息)

不,您不需要调用
myClass.clear()
。当无法通过活动引用访问对象时,它将有资格进行垃圾收集。这并不意味着它将被立即收集,但它将有资格收集

为了垃圾收集而将引用设置为null是非常不合适的,这样做会损害代码的可读性。当然也有例外-例如,
ArrayList
将在不再需要时将其内部缓冲区的元素设置为
null
,为了避免意外地阻止对象被垃圾收集,但通常只要对象本身是必需的,对象中的字段就有效且有用。简而言之,我几乎从来没有编写过像
MyClass.clear()
这样的方法,更不用说调用它了


也很少值得将局部变量设置为null。您在MyMain中的代码不清楚,因为它在方法之外无效。。。如果您的意思是所有代码都在一个方法中,那么您也不需要将
myClass
设置为null。当该方法完成时,该变量将不再作为它所引用的对象的GC根贡献—当然,如果存在其他GC根,则该对象仍然不能进行垃圾收集。但是,在方法末尾将局部变量设置为null是毫无意义的。

您甚至不需要将myclass设置为null。一旦它超出范围,它就有资格进行垃圾收集。

GC将处理所有与它无关的内容。因此,在处理了
MyClass
之后,将不会剩下对
myObject
的引用,因此它将被GC删除

在将myClass设置为null之前,是否需要调用myClass.clear(),以确保GC将删除myClass中的myObject

您不必调用clear,也不必将
myClass
设置为null

您也不能确定它是否会被收集,但是如果VM需要内存,那么当
myClass
it self不可引用时,它将是可删除的


所以在这种情况下你不必担心。

是的,你太偏执了。只要运行代码无法访问对象,它最终就会被收集(尽管“最终”可能意味着“当程序退出时”,如果内存充足且GC不需要运行的话)。不可访问对象中的引用也不可访问,因此就GC而言,它们不再起作用

但是请注意,这意味着
finalize
可能已经在您的子对象中运行,因此如果您想在finalizer中执行任何工作,您不能依赖任何非原语的子对象。

很少真正需要通过引用为空来“帮助”gc

以下是一个人为的情况,其中零位确实有帮助:

    long[] arr = new long[7000000];
    //arr = null;
    arr = new long[7000000];

如果您使用-Xmx100M运行此程序,它将失败并出现OutOfMemoryError。如果取消注释使arr为null的行,它将正常工作。发生这种情况的原因是,在创建另一个阵列时,arr引用仍保留着巨大的阵列。内存分配发生在分配之前,它触发垃圾回收,并且失败。当引用为空时,GC成功地获得了足够的空间。

是的,当它超出范围时,它将被GC删除。@Byron:不,绝对不。如果你的评论是一个答案,我会否决它。首先,对象不会超出范围——变量会。这有很大的区别。其次,在特定变量超出范围后,对象可能有资格进行垃圾收集,但这并不意味着它将在该点被收集。在某些情况下,将变量设置为null是值得的。例如,想象一下,如果
ArrayList
在删除元素并向下移动其余元素后在其支持数组中保留引用,那么从GC的角度来看,即使无法实际访问对象,也可以访问对象。@Jon:当然,我不会就此与您争论。但是,我认为完全合格和正确的答案对OP来说可能不太清楚