鉴于:
interface Animal {
void makeNoise();
}
class Horse implements Animal {
Long weight = 1200L;
public void makeNoise() {
System.out.println("whinny");
}
}
public class Icelandic extends Horse {
public void makeNoise() {
System.out.println("vinny");
}
public static void main(String[] args) {
Icelandic i1 = new Icelandic();
Icelandic i2 = new Icelandic();
Icelandic i3 = new Icelandic();
i3 = i1;
i1 = i2;
i2 = null;
i3 = i1;
System.out.println("end of program");
}
}
在最后一个语句中有多少对象符合垃圾收集器的条件(即:打印程序结束的地方)? 答案是4但我不明白他们是4并且最多有3个对象?
答案 0 :(得分:1)
你没有正确地看待这个。并非所有“冰岛”对象都有资格在此行进行垃圾回收。并且每个“Icelandic”对象都有另一个对象,特别是Long,当它包含“Icelandic”对象超出范围和/或不再具有对它的实时引用时,它也有资格进行垃圾收集。
在此示例中,原始i2对象和“属于它”的Long在System.log行之后才有资格进行垃圾回收。
答案 1 :(得分:1)
假设“at”表示“完全在之前”(就像我们对断点一样)。
如果您严格遵循语言规范,那么根据我的统计,有2个Icelandic
个对象符合垃圾回收条件,每个对象包含一个Long
,因此 4个对象合格总计。
在实际的实现中,通过它们通常使用的所有优化,许多其他数字都是可能的。例如:
args
从未在该点之下使用过,因此它在“正式”超出范围(加1,然后)之前是合格的。但是,随着优化的到位,剩余的Icelandic
对象及其Long
(以及另外2个)也将如此。 Long
个对象,因此实习值不会被垃圾收集(减去2或3,在这种情况下,取决于先前的优化是否到位)。 除非你对执行运行时的实现有一个非常透彻的了解,否则你实际上无法知道。
答案 2 :(得分:0)
简短的回答是问题没有答案。
包含命令行参数的String[]
可能在调用结束时符合GC的条件。 Long
值可能位于Long.valueOf
内部的缓存中,也可能不存在。
分配给随后未读取的局部变量不能保证对GC有影响,因为可以优化分配并且由于liveness analysis可以重用变量,并且这可能在JIT编译代码后发生变化。