符合垃圾回收条件的对象

  • 本文关键字:条件 对象 java scjp
  • 更新时间 :
  • 英文 :


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

根据凯西·塞拉的回答,这是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(

让我们逐行分解:

CardBoard c1 = new CardBoard();

我们现在有两个对象,CardBoard c1指向和Short c1.story。GC 都不适用于 CardBoard 处的 c1 点和ShortCardBoard点的story变量......

CardBoard c2 = new CardBoard();

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

CardBoard c3 = c1.go(c2);

我们在 c1 指向的 CardBoard 上调用方法,传递c2的值,这是对CardBoard对象的引用。我们将参数清空,但 Java 是按值传递的,这意味着c2变量本身不受影响。然后我们返回空参数。 c3 nullc1c2不受影响。我们仍然有 4 个对象,其中没有一个可以 GC'd。

c1 = null;

我们无效c1 .c1之前指向的CardBoard对象现在没有任何指向它的内容,它可以是GC'd。因为CardBoard对象内部的story变量是唯一指向Short的东西,并且因为CardBoard对象符合GC的条件,所以Short也有资格获得GC。这给了我们 4 个对象,其中 2 个可以是 GC'd。符合 GC 条件的对象是以前由 c1c1.story 引用的对象。

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

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

最初分配给c1的对象无法访问,因为c1引用设置为 null,但c2引用尚未更改,因此仍可通过c2引用从此范围访问分配给它的对象。

c3null的,所以显然没有对象有资格进行垃圾回收。

请注意,仅创建两个CardBoard对象,即以下行上的两个对象:

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

在参考杂耍之后,只有一个没有参考。

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

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的盒装等价物。让我们看看Short.valueOf()的Javadoc:

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

200 超出了"必须缓存"范围,因此属于"可能缓存"。如果缓存了,则当包含story实例时,CardBoard的值将不符合 GC 的条件。如果未缓存,story将无法访问,因此将进行 GC 处理。

为了使问题明确(并且建议的答案正确(,代码应像这样修改:

Short story = new Short(200);

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

如果您注意到代码中只创建了两个对象。 C3 永远不会初始化为对象,它是一个空引用。因此,只有一个"对象"符合垃圾回收条件。

最新更新