局部变量上的垃圾收集

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了局部变量上的垃圾收集相关的知识,希望对你有一定的参考价值。

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

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

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

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

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

答案

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

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

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

另一答案

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;
另一答案

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

以上是关于局部变量上的垃圾收集的主要内容,如果未能解决你的问题,请参考以下文章

一篇文章搞懂G1收集器

《javascript高级程序设计(第二版)》学习

带有变量分配的 Java 垃圾收集

javaScript 垃圾收集

C# 和 Java 中的垃圾收集

垃圾回收机制