【问题标题】:Eligible variables for garbage collection in JavaJava中垃圾收集的合格变量
【发布时间】:2012-11-29 21:08:50
【问题描述】:

我正在准备OCPJP,却被以下模拟考试题卡住了:

给定:

3. interface Animal { void makeNoise(); }

4. class Horse implements Animal {
5.     Long weight = 1200L;
6.     public void makeNoise() { System.out.println("whinny"); }
7. }

8. public class Icelandic extends Horse {
9.     public void makeNoise() { System.out.println("vinny"); }

10.    public static void main(String[] args) {
11.        Icelandic i1 = new Icelandic();
12.        Icelandic i2 = new Icelandic();
12.        Icelandic i3 = new Icelandic();
13.        i3 = i1; i1 = i2; i2 = null; i3 = i1;
14.    }
15. }

当到达第 14 行时,有多少对象符合垃圾收集器的条件?

A. 0

B. 1

C. 2

D. 3

E. 4

F。 6

他们的正确答案是 E,即四个物体,但我不知道为什么。从我的角度来看,i2 及其权重将有资格进行垃圾收集。也许我遗漏了什么,请指教。

【问题讨论】:

  • 他们的问题有点傻,因为垃圾收集与程序终止无关(第 14 行)...
  • 澄清一下 - 你确定weightLong 而不是long(对象,而不是原始对象)?
  • 等等……这不完全取决于这个程序的调用方式吗?字符串是对象,因此提供的任何参数都会改变对象的数量。
  • 那些String 在字符串常量池中,所以它们不符合垃圾回收的条件(至少在问题的意义上)。
  • 是的,我确定权重很长,我复制粘贴了整个代码。

标签: java garbage-collection ocpjp


【解决方案1】:

让我们在第 11 行 IceA、第 12 行 IceB 等上调用 Icelandic()

创建后

i1 = IceA
i2 = IceB
i3 = IceC

i3 = i1之后

i1 = IceA
i2 = IceB
i3 = IceA

i1 = i2之后

i1 = IceB
i2 = IceB
i3 = IceA

i2 = null之后

i1 = IceB
i2 = null
i3 = IceA

i3 = i1之后

i1 = IceB
i2 = null
i3 = IceB

所以只剩下第 12 行创建的 Icelandic()。现在,每个Icelandic() 都有一个Long weight,所以IceAIceC 现在没有被引用,这意味着4 个对象(IceAIceA.weightIceCIceC.weight)可用于GC。


其他问题:

  1. args 仍然是 args,他们不计入这个问题的范围
  2. Long weight 不是静态声明的,因此类的每个实例都有一个 weight 对象。

【讨论】:

  • 那么重量呢?
  • 但是在第 14 行,所有i1i2i3 都超出了范围,所以IceB 也可以被GC,确定吗?
  • @DNA:那是我最初的答案,但答案是 6。很明显,提问者想知道 gc 在超出范围之前有什么可用的。
  • 啊,糟糕的考题的乐趣 ;-)
【解决方案2】:

我们将创建的第一个冰岛对象称为“A”,第二个称为“B”,第三个称为“C”。在第 12 行之后,它们分别被 i1、i2 和 i3 引用。

现在,我们这样做:

i3 = i1; // object "C" is no longer referenced, object "A" is now referenced by i1 and i3
i1 = i2; // object "A" is just referenced by i3, object "B" is referenced by i1 and i2
i2 = null; // object "B" is just referenced by i1 now
i3 = i1; // object "B" is referenced by i1 and i3, object "A" is no longer referenced

因此,对象“A”和“C”不再被引用,并且它们连同它们的“权重”都符合垃圾回收条件,因此总共有四个对象。

【讨论】:

  • 但是所有这些引用都超出了范围,因此不会阻止任何这些对象的 GC
  • @DNA,我认为“当到达第 14 行时”是指在退出 main() 之前。显然,如果答案是 4,这就是问题作者的意图。
  • @DNA:我同意你的观点,但我认为提问者说的是“在第 14 行之前”,而不是“在变量超出范围之后”
  • 啊,这可以解释它 - 它完全改变了问题的含义,并使第 13 行的所有乱七八糟的东西都相关(否则它在考试问题中是一个相当残酷的转移!)
  • 对,问题作者最好在第 14 行插入实际的代码行(如 System.out.println() 或类似的东西)而不是右大括号。
【解决方案3】:

系统中有 4 个对象,3 个 Icelandic 实例和 1 个 Long 实例。

当您将常量对象分配给某个变量时,编译器使用一种由所有weight 实例共享的private static final Long long1200 = Long.valueOf(1200L); 对象。

原始类型包装器是不可变的,因此进行这种优化是安全的。

编辑:可能我错了,因为如果我们在这里多次引用相同的常量,这将起作用,但事实并非如此

【讨论】:

  • 您是半正确的:编译器或 Long 实现 正在 优化较小数量的实例,使其只有一个。对于更大的数字不再:ideone.com/nsQoHr
  • 没错,这是Long.valueOf()的运行时优化,我以为编译器也做了不断的优化,这似乎是错误的
猜你喜欢
  • 1970-01-01
  • 2011-01-06
  • 1970-01-01
  • 1970-01-01
  • 2010-12-13
  • 2011-02-25
  • 2018-06-10
  • 1970-01-01
相关资源
最近更新 更多