2015-10-21 157 views
3

我正在通过Java垃圾收集过程以及GC适用的不同场景。Java垃圾收集场景

下面是这种情况下我感到困惑:

List<X> listX = new ArrayList<X>(); 

    for(int a = 0;a<100;a++){ 
     listX.add(new X(a)); 


    } 

    for (X xObject : listX) { 
     xObject.printValue(); 
    } 

在第一圈我添加在每个循环的新对象,并在最新的循环,我只是打印的值,因此,那些对象我在列表中添加了适用于GC的列表?

这句话是什么意思? “

”另一个很好的例子是什么时候一个实例可以成为垃圾收集的资格,一个实例的所有属性都可以存储在寄存器中,然后访问这些寄存器来读取这些值。这些值将被写回到实例中虽然这些值可以在未来使用,但仍然可以将此实例标记为垃圾回收“

+0

它高度依赖于变量的给定范围和周围列表的范围,我会说。列表中的条目仍然会被列表引用,因此它们本身不适用于gc。 –

回答

9

不,它们不是,因为它们是由数组引用的ArrayList的引用位于当前线程的堆栈中:

thread stack --> ArrayList --> array --> x1, x2, x3, etc. 
3

添加到列表中的对象的生命周期与list本身的生命周期有关,因为从我从代码中看到的内容中,listX是唯一持有对X对象的引用的对象。 因此,当listX不再被引用时,将会收集到对象X。 检查@JBNizet以查看它们如何被实际引用或连接(+1)。总是这样想,我的对象是如何连接的,如果他们仍然被引用一路回GC Roots,并记住Java是聪明的,它不会做reference counting :)

0

垃圾收集只释放那些被对象持有的内存不再可以从任何根访问,例如在循环依赖的情况下。每个新的X对象的引用都保存在List中,因此它们不会被垃圾收集。

+0

这是不正确的。如果仍然不能从任何根目录强力访问仍然被引用的对象,则可以对其进行GC处理。允许循环依赖关系被启用:A - > B和B - > A. –

+0

谢谢,@JBNizet;我会更新答案。 –

+0

@AndyDavies那是错的 –

1

如果您考虑以下代码,请稍微更改它。

List<X> listX = new ArrayList<X>(); 

    for(int a = 0;a<100;a++){ 
     X tmpX = new X(a); 
     X unusedX = new X(a); 

     listX.add(tmpX); 
} 

当调用new关键字时,会在堆上创建一个新对象。这意味着在这个例子中,它将创建一个tmpX和一个unusedX。您将tmpX添加到阵列,因此这意味着它在ListX中有参考。当它是垃圾收集时间时,垃圾收集器将检查那里的对象只存在于范围的当前迭代中,由{}方括号定义。 unusedX将被收集,但由于tmpX将在列表中有一个参考,它将保存在堆中。

0

不,如果这段代码是可到达的,如果不可以,它将是难以辨认的。垃圾收集器将查找没有被使用的对象,摆脱它们并释放内存。