【问题标题】:Java garbage collection scenarioJava 垃圾回收场景
【发布时间】:2016-01-20 09:34:48
【问题描述】:

我正在经历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

这句话是什么意思?

“还有一个很好的例子,说明实例何时可以进行垃圾回收。实例的所有属性都可以存储在寄存器中,然后访问寄存器以读取值。将来不会有这样的情况这些值将被写回实例。虽然这些值将来可以使用,但仍然可以将此实例标记为符合垃圾回收条件"

【问题讨论】:

  • 这在很大程度上取决于变量的给定范围和我要说的周围列表的范围。您列表中的条目仍被您的列表引用,因此它们本身不适用于 gc。

标签: java garbage-collection


【解决方案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 将在列表中具有引用,因此将其保留在堆中。

【讨论】:

    【解决方案2】:

    不,如果这段代码是可访问的,否则它将难以辨认。垃圾收集器将寻找不再使用的对象,将其清除并释放内存。

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

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

        【讨论】:

        • 这是不正确的。如果它们不再可以从任何根强烈访问,则仍然被引用的对象可以被 GCed。允许循环依赖被 GCed 的原因是:A -> B 和 B -> A.
        • 嗯,听起来我对垃圾收集的了解并不像我想象的那么多……你能否详细说明为什么它是错误的/哪些部分是错误的,@SleimanJneidi?
        【解决方案5】:

        不,它们不是,因为它们被数组引用,而数组被引用在当前线程堆栈中的 ArrayList 引用:

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

        【讨论】:

          猜你喜欢
          • 2014-03-09
          • 1970-01-01
          • 1970-01-01
          • 2011-06-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多