符合垃圾收集条件的对象

时间:2012-07-19 15:27:19

标签: java scjp

此问题来自Kathy Sierra SCJP 1.6。有多少个对象符合垃圾收集的条件?

根据Kathy Sierra的回答,这是C。这意味着两个对象有资格进行垃圾回收。我给出了答案的解释。 但为什么c3不符合garbage collection(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条件?

  • A:0
  • B:1
  • C:2
  • D:编译失败
  • E:无法知道
  • F:运行时抛出异常

答案:

  • C是正确的。只有一个CardBoard对象(c1)符合条件,但它有一个相关的Short包装器对象也符合条件。
  • 基于上述情况,A,B,D,E和F不正确。 (目标7.4)

5 个答案:

答案 0 :(得分:7)

让我们逐行打破这个:

CardBoard c1 = new CardBoard();

我们现在有两个对象,CardBoard c1点和Short c1.story。对于GC c1以及CardBoardstoryCardBoard变量Short点,GC都不可用。

CardBoard c2 = new CardBoard();

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

CardBoard c3 = c1.go(c2);

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

c1 = null;

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

答案 1 :(得分:6)

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

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

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

答案 2 :(得分:4)

c3null,因此显然没有符合垃圾回收条件的对象。

请注意,只创建了两个CardBoard个对象,这两个对象在这些行中:

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

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

答案 3 :(得分: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的盒装等价物。让我们看一下Short.valueOf()的Javadoc:

  

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

200超出“必须缓存”范围,因此它属于“可以缓存”。如果它被缓存,story的值在包含CardBoard实例的情况下将不符合GC的条件。如果未缓存,则story将无法访问,因此无法进行GCed。

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

Short story = new Short(200);

更新: Short.valueOf()的{​​{3}}比我引用的1.8版本更加神秘,但同样的逻辑适用:没有办法只通过查看在代码中是否将返回Short的新实例或缓存实例。

答案 4 :(得分:-1)

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