局部变量上的垃圾收集

时间:2010-11-09 20:23:25

标签: java garbage-collection

我是一名进入Java世界的C ++程序员。而且我无法摆脱不得不让Java垃圾收集器进行清理的坏感觉。

例如,这段代码如何在Java中运行?

public void myFunction() {
    myObject object = new myObject();
    object.doSomething();
}

当myFunction()退出时,是否会删除局部变量对象?

我必须在退出之前将对象设置为null,还是超出范围并被GC删除?或者,在最坏的情况下,它会像在C ++中一样泄漏吗?

3 个答案:

答案 0 :(得分:26)

在不再使用之后的某个时刻,它将被垃圾收集。我相信Java的当前实现它实际上会持续到方法结束,而.NET中的垃圾收集器更具侵略性。 (我不知道是否有任何保证,即使在Java中。通常你只需希望本地变量在你调试时保持超出其最后可能的读数。)

但不,你不需要将变量设置为null,这样做会损害可读性。

在方法退出后,对象不太可能立即回收 ;这取决于GC运行的时间......当然,如果其他任何东西保留在对象的引用上,它可能无法进行垃圾收集。不要忘记变量的值只是一个引用,而不是对象本身。 (这可能需要一段时间才能习惯来自C ++。)

答案 1 :(得分:2)

GC至少在内存限制接近时完成工作,因为超出范围的变量引用的任何对象都可以被垃圾收集,但是最后一个退出块的超出范围的局部变量存在意外行为。

要深入了解,让我们进行比较:

{
   final List myTooBigList = new ArrayList();
   ... overfill the list
}
somethingRunOutOfMemory();

somethingRunOutOfMemory()因为myTooBigList不是GCable,尽管不在范围内且声明了更多内存,不像以下内容:

{
   final List myTooBigList = new ArrayList();
   ... overfill the list
}
Object fake = null;
somethingDoesNotRunOutOfMemory();

fake的影响将堆栈指针移回并让myTooBigList GCable,然后GC在内存限制接近时立即执行其工作。 令人惊讶的是(至少在我正在测试的jvm中)我们必须明确地在同一级别重用堆栈。一旦块退出,可以预期局部变量是GCable,但我想这是对性能的妥协。它会使字节码复杂化。

与C类似,局部变量位于帧旁边的堆栈中。 堆栈指针保留了范围内局部变量所需的空间。 当重用堆栈时,{exited block}的局部变量变为GCable,即:在同一堆栈级别,函数返回后或退出评估(catch,循环条件)之后声明局部变量之后。

他们是GCable之后:

try { } catch : after exit by catch because catch reuses stack
for { } : after exit loop condition  because evaluation reuses stack
while { } : after exit loop condition because evaluation reuses stack
{ } declare=value : after any declaration+affectation that reuses stack

它们之后才是GCable:

try { } : after nothing caught
for { } : after exit by break
while { } : after exit by break
do { }
if { }
{ }

注意:对于实验室,请运行GC,然后将WeakReference(my variable)null进行比较。

final WeakReference gctest;
{
   final List myTooBigList = new ArrayList();
   gctest = new WeakReference(myTooBigList);
   ... overfill the list
}
Object fake = null;
System.gc();
assert gctest.get() == null;

答案 2 :(得分:1)

它将超出范围。在Java中,当没有人再指向一个对象时,它将被垃圾收集,或者至少它可用于垃圾收集。这里不需要将其设置为null。如果您的对象将存在于App中,则有时需要将对象引用设置为null,但是它所持有的引用需要进行垃圾回收。在这种情况下,您选择发布参考。