在我为OCJP学习时,我遇到了以下问题:
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
}}
当达到// doStuff时,有多少对象符合GC的条件?
正确答案是2,表示c1
及其story
对象。
当达到// doStuff行时,c3也为空。为什么它也不符合GC的条件?
答案 0 :(得分:3)
c3是一个带有空引用的本地句柄,它不指向(并且已经指向)已分配的对象。因此GC没什么。
答案 1 :(得分:1)
c3
不是对象。它是一个引用null的变量。变量不能符合GC的条件。只有对象才有资格使用GC。
符合GC条件的对象是最初由c1
引用的Cardboard,最初由CardBoard引用的Short实例最初由c1
引用。
答案 2 :(得分:1)
垃圾收集器扫描内存中的对象,以及何时找到指向它的句柄的一个检查(而不是反之) 当调用垃圾收集器时,从内存中删除没有指向它们的句柄的对象(内部内存)。在这个代码场合,你只有2个在内存中创建的对象但是有三个句柄。垃圾收集器将仅删除最多2个对象(因为只存在两个对象)C3仅指向空位置。 C1,C2,C3未被删除。它们用于指向的对象将被删除(如果没有其他句柄指向它们)。因此,此时由于C3从未指向内存中的对象,因此将其设置为null对垃圾收集器没有任何影响。
希望我有所帮助
答案 3 :(得分:0)
您的CardBoard#go()
方法无效。它接收对某个对象的引用,立即忘记它,替换为null
,并返回此null
值。
所以,行
CardBoard c3 = c1.go(c2);
也没有做任何事情,即没有创建任何对象。只为null分配给c3
。所以它不是垃圾收集因为它已经不存在了。
答案 4 :(得分:0)
c3 本身只是一个引用变量,它不在堆空间中(即不是在垃圾收集范围内)
行CardBoard c3 = c1.go(c2);
仅将c3引用设置为null
因此,c3对垃圾收集没有影响,因为它不会使任何对象符合条件。
答案 5 :(得分:0)
c3没有对象的引用,只是为了让人产生一些困惑。
我们创建了两个对象c1和c2,我们遗漏的是Short类型的包装器对象,所以基本上我们总共创建了四个对象。
当我们使c1 = null时,意味着我们使用c1访问的短对象可用于GC,而不是我们可以使用c2访问的短对象。
可以使用以下代码验证:
公共类CardBoard {
Short story = 200;
CardBoard go(CardBoard cb) {
cb = null;
return cb;
}
public static void main(String[] args) {
Runtime run = Runtime.getRuntime();
CardBoard c1 = new CardBoard();
CardBoard c2 = new CardBoard();
CardBoard c3 = c1.go(c2);
// System.out.println(run.freeMemory());
run.gc();
// System.out.println(run.freeMemory());
c1.story = 100;
System.out.println(c1.story);
c1 = null;
run.gc();
System.out.println(c2.story);
}
}
输出: 100 200
这意味着我们可以从c1访问的c1和短篇故事可用于垃圾收集而不是c2的简短故事。