java垃圾收集和null引用

在我为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的条件?

c3是一个带有空引用的本地句柄,它不指向(并且已经指向)已分配的对象。 因此对GC没有任何意义。

c3不是一个对象。 它是一个引用null的变量。 变量不能符合GC的条件。 只有对象才有资格使用GC。

符合GC条件的对象是最初由c1引用的Cardboard,最初由CardBoard引用的Short实例最初由c1引用。

垃圾收集器扫描内存中的对象,当它找到一个检查指向它的句柄时(而不是反之)当调用垃圾收集器时,没有句柄指向它们的对象(内部内存)将从内存中删除。 在这个代码场合,你只有2个在内存中创建的对象但是有三个句柄。 垃圾收集器将仅删除最多2个对象(因为只存在两个对象)C3仅指向空位置。 C1,C2,C3未被移除。 它们用于指向的对象将被删除(如果没有其他句柄指向它们)。 所以此时由于C3从未指向内存中的对象,因此将其设置为null对垃圾收集器没有任何影响。

希望我有所帮助

你的CardBoard#go()方法什么都不做。 它接收对某个对象的引用,立即忘记它,替换为null ,并返回此null值。

所以,这条线

 CardBoard c3 = c1.go(c2); 

也什么都不做,即没有创建对象。 只为null分配给c3 。 所以它不是垃圾收集因为它已经不存在了。

c3本身只是一个引用变量 ,它不在堆空间中 (即不在垃圾收集的范围内)

线CardBoard c3 = c1.go(c2); 仅将c3引用设置为null因此,c3对垃圾回收没有影响,因为它不会使任何对象符合条件。

c3没有对象的引用,只是让人产生一些困惑。

我们创建了两个对象c1和c2,我们遗漏的是Short类型的包装器对象,所以基本上我们总共创建了四个对象。

当我们使c1 = null时,它意味着我们使用c1访问的短对象可用于GC,而不是我们可以使用c2访问的短对象。

这可以使用以下代码进行validation:

公共类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的短篇故事。