java垃圾收集和null引用

时间:2012-10-28 14:35:20

标签: java garbage-collection scjp

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

6 个答案:

答案 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的简短故事。