Java垃圾收集场景

3
我正在学习Java垃圾回收的过程以及不同适用于GC的场景。
以下是我感到困惑的场景:
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吗?
这句话是什么意思?
“当一个实例可以成为垃圾收集的候选对象时,这是一个更好的例子。实例的所有属性都可以存储在寄存器中,然后将访问寄存器以读取值。将来没有情况会将值写回到实例中。尽管值可以在将来使用,但此实例仍可标记为垃圾收集的候选对象。”

我认为这高度取决于变量的给定范围和周围列表的范围。您列表的条目仍由列表引用,因此它们本身不适用于垃圾收集。 - Aron_dc
5个回答

9
不是,因为它们被数组引用,而该数组又被ArrayList引用,该ArrayList的引用在当前线程的堆栈中:
thread stack --> ArrayList --> array --> x1, x2, x3, etc.

3
您添加到列表中的对象的生命周期与list本身的生命周期有关,因为根据我从代码中看到的,listX是唯一一个持有对X对象引用的对象。因此,当listX不再被引用时,X对象将被回收。@JBNizet可以查看它们实际上是如何被引用或连接的(+1)。始终思考这样的问题,我的对象是如何连接的,它们是否仍然被引用直至GC Roots,请记住,Java很聪明,它不使用引用计数 :)

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中具有引用。在进行垃圾回收时,垃圾回收器将检查仅在{}括号定义的for范围内活动的对象。unusedX将被收集,但由于tmpX在列表中具有引用,因此它保留在堆上。

0

垃圾回收仅释放不再从任何根对象强可达的对象所占用的内存,例如在循环依赖的情况下。对于每个新的X对象的引用都保存在List中,因此它们不会被垃圾回收。


这是不正确的。如果对象不再从任何根引用强可达,它们仍然可以被垃圾回收。这就允许循环依赖项被垃圾回收:A -> B 和 B -> A。 - JB Nizet
嗯,听起来我对垃圾回收的了解不如我想象的那么多... @SleimanJneidi,你能详细说明一下哪里错了吗?为什么错了? - Andi Emma Davies

0
不,如果这段代码是可达的,否则它将是无效的。垃圾收集器将寻找不再使用的对象,将其清除并释放内存。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接