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;
}
在将myClass设置为null之前,是否需要调用myClass.clear()以确定GC是否会删除myClass中的myObject?或者将myClass设置为null并且GC将删除所有嵌套对象就足够了吗?
也许我有点偏执,答案就像“GC最终将删除任何正在运行的代码或任何未来可用代码无法访问的任何对象”一样简单。因此,如果一个创建的对象不可用,或者永远不可用,在任何正在运行的代码中,它最终会成为GC的受害者,即使它被嵌套并使C ++程序员感到害怕?
答案 0 :(得分:9)
不,您无需致电myClass.clear()
。当无法通过实时引用到达对象时,它将有资格进行垃圾回收。这并不意味着它会被立即收集,但它将符合条件进行收集。
非常很少适合为垃圾收集设置对null的引用 - 这会损害代码的可读性。当然也有例外 - 例如,ArrayList<T>
将不再需要时将其内部缓冲区的元素设置为null
,以避免意外阻止对象被垃圾收集 - 但通常只要对象本身是必需的,对象中的字段就是有效且有用的。简而言之,我几乎不会编写类似MyClass.clear()
的方法,更不用说调用它了。
将局部变量设置为null也很少值得。您在MyMain
中的代码不清楚,因为它在方法之外无效...如果您将所有代码放在方法中,那么您不需要设置myClass
也为空。当方法完成时,变量将不再作为它所引用的对象的GC根目录 - 当然,如果其他 GC根目录存在,该对象仍然不符合垃圾回收的条件。但是,在方法结束时将局部变量设置为null是没有意义的。
答案 1 :(得分:8)
您不 将任何设置为null,以便将其设为GC。不要偏执。
不要尝试像C ++一样编写Java。
答案 2 :(得分:7)
很少真正需要通过引用归零“帮助”gc。
这是一个人工案例,其中归零有帮助:
long[] arr = new long[7000000];
//arr = null;
arr = new long[7000000];
如果使用-Xmx100M运行它,它将因OutOfMemoryError而失败。如果取消注释使arr为null的行,它将正常工作。发生这种情况是因为arr引用仍在保留巨大的数组,而另一个正在创建。内存分配在赋值之前发生,它触发垃圾收集,并且失败。在使引用归零时,GC成功创建足够的空间。
答案 3 :(得分:2)
不,您不需要先致电clear
。 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
相互引用的问题
the JLS中的详细信息(很多细节)。
答案 4 :(得分:1)
是的,你过于偏执。只要通过运行代码无法访问对象,它最终将被收集(尽管“最终”可能意味着“当程序退出时”,如果有足够的内存并且GC不需要运行)。无法访问无法访问的对象中的引用,因此就GC而言,它们不再计算在内。
请注意,这意味着finalize
可能已经在您的子对象中运行,因此如果您想要做任何工作,您不能依赖任何不是原始的子东西在终结者中。
答案 5 :(得分:0)
GC最终会正确处理对象。我想你可能有点过于偏执。虽然将对象设置为null并没有什么坏处。
要回答你的问题,如果你调用myObject.clear只执行myObject = null,那么没有理由再将它重置为null。
答案 6 :(得分:0)
您甚至不需要将myclass设置为null。一旦超出范围,就有资格进行垃圾收集。
答案 7 :(得分:0)
GC会处理所有没有参考的东西。因此,在处理MyClass
之后,myObject
将不会有任何引用,因此它将被GC删除
答案 8 :(得分:0)
在将myClass设置为null之前,是否需要调用myClass.clear()以确定GC是否会删除myClass中的myObject?
您不必调用clear,也不必将myClass
设置为null。
您无法确定它是否会被收集,但如果VM需要内存,则当myClass
自身不可引用时,它将是可读的。
所以在这种情况下你不需要担心。