我被问到一个问题(在这个网站上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引用的对象有资格进行垃圾回收。”但为什么?它们包含彼此的循环引用,它们可以相互访问。
谢谢!
答案 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()的构造函数中,实例化B()“第二个对象”的实例a ------------这指向对象------------> A()“第一个对象”
在B类实例中只是指向上面的A(),因此没有创建新对象。 在为“a”变量指定空值时,没有引用将指向A()对象。现在您有2个符合GC要求的对象。不要担心类会引用彼此,只关注main方法中的声明。