6

这个问题取自Kathy Sierra SCJP 1.6。有多少对象符合垃圾回收条件?

根据 Kathy Sierra 的回答,它是C. 这意味着两个对象有资格进行垃圾回收。我已经给出了答案的解释。但是为什么c3不符合垃圾回收(GC)的条件呢?

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);
    c1 = null;
    // Do stuff
} }

何时// Do stuff达到,有多少对象符合 GC 条件?

  • 答:0
  • 乙:1
  • C: 2
  • D:编译失败
  • E:不可能知道
  • F:运行时抛出异常

回答:

  • C 是正确的。只有一个 CardBoard 对象 (c1) 符合条件,但它有一个关联的Short包装对象也符合条件。
  • A、B、D、E、F 根据以上判断是不正确的。(目标 7.4)
4

5 回答 5

7

让我们逐行分解:

CardBoard c1 = new CardBoard();

我们现在有两个对象,CardBoard c1点 和Short c1.story。GC 中的c1CardBoard和点的变量story都不能用于...CardBoardShort

CardBoard c2 = new CardBoard();

与上面类似,我们现在有四个对象,没有一个可用于 GC。

CardBoard c3 = c1.go(c2);

我们在 指向的 CardBoard 上调用 go 方法c1,传递其值是对Objectc2的引用。CardBoard我们将参数设为空,但 Java 是按值传递的,这意味着c2变量本身不受影响。然后我们返回空参数。c3nullc1并且c2不受影响。我们还有 4 个对象,没有一个可以被 GC 处理。

c1 = null;

我们为空c1。之前指向的CardBoard对象c1现在没有任何指向它,它可以被 GC'd。因为该对象story内的变量CardBoard是唯一指向 的东西Short,并且因为该CardBoard对象有资格进行 GC,所以Short也有资格进行 GC。这给了我们 4 个对象,其中 2 个可以被 GC 处理。符合 GC 条件的对象是以前由c1和引用的对象c1.story

于 2012-07-19T15:42:50.320 回答
6

从来没有存在过c3指向的对象。c1构造函数只被调用了两次,两个对象,一个由and指向c2c3只是一个引用,除了空指针之外从未分配过任何东西。

当前指向 null的引用c3不会超出范围并从堆栈中删除,直到跨过 main 方法末尾的右大括号。

最初分配给它的对象c1是不可达的,因为c1引用被设置为null,但是c2引用并没有改变,所以分配给它的对象仍然可以通过c2引用从这个范围内到达。

于 2012-07-19T15:36:30.123 回答
4

c3null,所以显然没有符合垃圾收集条件的对象。

请注意,仅CardBoard创建了两个对象,这两个对象位于以下行:

CardBoard c1 = new CardBoard();
CardBoard c2 = new CardBoard();

在引用杂耍之后,只有其中一个是没有引用的。

于 2012-07-19T15:29:33.650 回答
1

正式正确的答案是我们不知道。而我们不知道的原因是这一行:

Short story = 200;

这编译为以下字节码:

CardBoard();
Code:
   0: aload_0
   1: invokespecial #1                  // Method java/lang/Object."<init>":()V
   4: aload_0
   5: sipush        200
   8: invokestatic  #2                  // Method java/lang/Short.valueOf:(S)Ljava/lang/Short;
  11: putfield      #3                  // Field story:Ljava/lang/Short;
  14: return

第 8 行是这里的关键Short.valueOf(),它返回一个盒装的原语等价物200。让我们看一下Javadoc Short.valueOf()

此方法将始终缓存 -128 到 127(含)范围内的值,并且可能缓存此范围之外的其他值。

200 超出了“必须缓存”范围,因此属于“可能缓存”。如果它被缓存,那么当它的包含实例是时,它的值story将不符合 GC 的条件。CardBoard如果它没有被缓存,story将无法访问并因此被 GC。

为了使问题明确(并且建议的答案正确),代码应修改如下:

Short story = new Short(200);

更新:Javadoc的1.6 版本比我引用的Short.valueOf()1.8 版本更神秘,但同样的逻辑适用:仅通过查看代码无法判断是否Short将返回新的或缓存的实例。

于 2016-03-18T12:59:05.847 回答
-1

如果您注意到代码中只创建了两个对象。c3 从未初始化为对象,它是一个空引用。因此,只有一个“对象”有资格进行垃圾收集。

于 2012-07-19T15:38:45.793 回答