【问题标题】:Which objects are eligible for GC?哪些对象符合 GC 条件?
【发布时间】:2010-09-08 10:39:49
【问题描述】:
class CardBoard {
  Short story = 200;
  CardBoard go(CardBoard cb) {
    cb = null;
    return cb;
  }
  public static void main(String[] args) {
    CardBoard c1 = new CardBoard();
    CardBoard c2 = new CardBoard();
    CardBoard c3 = c1.go(c2);
     System.out.println("c3 value : "+c3);
     c1 = null;
     System.out.println("c1 value : "+c1);
     System.out.println("c2 value : "+c2);
    // do Stuff
  } 
}

这是 SCJP6 模拟考试的一个示例。问题是:当达到 //doStuff 时,有多少对象符合 GC 条件?答案是(2 个对象),因为:只有一个 CardBoard 对象 (c1) 符合条件,但它有一个关联的 Short 也符合条件的包装对象。

当我执行代码时,看起来 c3 也指向 null...所以我会说 3 个对象有资格进行 GC。

谁能指导我理解这段代码的逻辑。

【问题讨论】:

    标签: java garbage-collection


    【解决方案1】:

    对象c3 原本是空的,所以不存在回忆它的问题,因为它从一开始就不存在。垃圾收集器旨在清除堆上实际存在的对象。

    其中,对c2 的引用永远不会被丢弃,因此不会被回收。尽管在声明 CardBoard c3 = c1.go(c2); 中似乎 c2 无效,但事实并非如此。对c2 的引用已按值传入,尽管该引用已无效,但在 main 方法中存在对该对象的现有引用。因此它不会被回收。

    这给我们留下了c1,它已被明确无效,因此有资格收集。但是,c1 还包含对 Short 变量故事的引用,它没有来自任何其他对象的任何入站引用。这会导致两个对象符合清除条件 - 一个 CardBoard 对象和嵌入的 Short 对象。

    【讨论】:

    • 或者,简单地说:在该代码中,new 关键字只有两种情况,它们只执行一次(它们在 main 方法中,而不是在迭代中)。所以根据定义,这段代码只创建了两个对象。它怎么能收集更多?
    • @Joeri,毫无疑问你是对的。但是,仅根据创建的对象的数量来推断适合收集的对象的数量并不容易。是的,这是一个很好的指标,但计算强引用更重要,仅仅阅读代码很容易出错。
    • 当然,我完全同意。只是在这种情况下,代码非常简单,你甚至不需要再看下去。不过仍然是一个很好的练习。
    • @Joeri Short story = 200 在不使用 new 的情况下创建了一个对象,所以实际上这段代码创建了 4 个对象,其中 2 个可以在 doStuff 中进行 gc,其中 2 个不可以。
    【解决方案2】:

    CardBoard c1 = new CardBoard();

    创建一个CardBoard 实例及其Short 实例。 (2个对象) 将CardBoard 引用分配给c1

    CardBoard c2 = new CardBoard();

    创建另一个CardBoard 实例及其Short 实例。 (另外 2 个对象) 将CardBoard 引用分配给c2

    纸板 c3 = c1.go(c2);

    null 分配给c3。 (go 方法是一个技巧,可以查看您是否了解 Java 参数传递语义。如果您认为 Java 使用按引用传递,您可能会错误地断定 c2 被此调用设置为 null。在事实上,c2 没有改变。)

    c1 = null;

    null 分配给c1。这会导致第一个 CardBoard 实例及其 Short 实例无法访问,并成为垃圾回收的候选对象。

    第二个CardBoard 实例及其Short 实例仍然可以访问。

    【讨论】:

      【解决方案3】:

      c3 从不指向任何对象,它始终是一个空变量。因此,对象 c3 不符合 GC 条件

      【讨论】:

        【解决方案4】:

        在您的代码中,只有 c1 和 c1 中包含的故事(短)符合 GC 条件。 即 2 个对象。

        c3 从不引用任何对象,因为 go() 方法返回 null。

        c2 不符合 GC 条件。正如在 Java 中,方法参数是按值传递的。并且当调用 go 方法时 c2 一直指向 object ,尽管在 go 方法中传递的变量被分配为 null。

        【讨论】:

        • 不正确。 c2 引用永远不会分配nullgo 方法是查看读者是否理解 Java 不使用 pass-by-reference 的一个技巧。
        • // doStuffc2 仍然引用 CardBoard,因此符合 gc 条件。正如 Vineet 的回答所说,这两个对象是 c1 和其中的 Short
        • 谢谢我已经用我引用错误的信息更新了我的答案:(。
        猜你喜欢
        • 2018-03-21
        • 2017-12-26
        • 2017-01-31
        • 1970-01-01
        • 2016-04-06
        • 1970-01-01
        • 2016-09-28
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多