SCJP模拟问题:有多少对象有资格进行垃圾回收?

时间:2011-04-27 09:09:47

标签: java garbage-collection scjp

我被问到一个问题(在这个网站上http://scjptest.com/):这行代码示例中有多少个对象符合垃圾收集的条件//某些代码在这里?

class A {
    private B b;
    public A() {
        this.b = new B(this);
    }
}

class B {
    private A a;
    public B(A a) {
        this.a = a;
    }
}

public class Test { 
    public static void main(String args[]) {
        A aa = new A();
        aa = null;
        // some code goes here
    }
}

正确的答案是:“a和b引用的对象有资格进行垃圾回收。”但为什么?它们包含彼此的循环引用,它们可以相互访问。

谢谢!

4 个答案:

答案 0 :(得分:5)

  

它们包含彼此的循环引用,它们可以相互访问。

是的,但它们不再可以从其他任何地方访问,因此无法在程序中看到和使用它们。

早期的GCs在收集此类自我引用对象组时遇到了问题,但对于现代世代收集器而言,这是一个已解决的问题。

简而言之,GC可以浏览已知静态和堆栈对象的引用Web,以及

  • 将找到的所有对象复制到新的内存池中,自动留下任何“死”对象(这是“年轻一代”策略),或者
  • 标记找到的所有对象,以便遍历遍历整个引用网络后,它可以删除所有未标记的对象(这是“旧/终身代”策略)。

答案 1 :(得分:2)

这是因为java有一个世代垃圾收集器,所以它可以收集在它们之间有引用的对象组,但不能从应用程序中收集。

有更深入的解释here

据我记得(我可能错了)这与旧版本的java(例如java 1.2)不同,其中必须手动清除循环依赖项以便GC收集它们。

答案 2 :(得分:2)

如果无法从任何线程访问该“孤岛”(或群组)中的任何对象,GC可以删除所谓的“对象岛”!

在您的示例中,您创建了一个对象A,该对象具有指向另一个对象B的链接。但是对象B不是任何人都期望的“可引用”的A.您可以将这两个对象视为孤岛。 当A消失时,GC将足够智能,以确定B不能被任何其他线程引用,因此您将删除2个对象。

答案 3 :(得分:1)

让我们清楚地了解情景。

A a = new A() 
  

a ------------这指向对象------------> A()“第一个对象”

在A()的构造函数中,实例化B()“第二个对象”的实例

在B类实例中只是指向上面的A(),因此没有创建新对象。 在为“a”变量指定空值时,没有引用将指向A()对象。现在您有2个符合GC要求的对象。不要担心类会引用彼此,只关注main方法中的声明。