Java和垃圾收集中的循环引用

Java和垃圾收集中的循环引用,java,garbage-collection,Java,Garbage Collection,假设我有如下所述的课程: class A { private B b; public A { b = new B(this); } } class B { private C c; private A a; public B(A a) { this.a = a; c = new C(this); } public removeRefereceToC() { c

假设我有如下所述的课程:

class A {
    private B b;

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

class B {
    private C c;
    private A a;

    public B(A a) {
        this.a = a;
        c = new C(this);
    }

    public removeRefereceToC() {
        c = null;
    }
}

class C {
    private B b;
    public C(B b) {
        this.b = b;
    }
}
若我们看一个参考图,a参考B(和B参考a),B参考C(和C参考B)。现在,如果我们调用B的方法removeReferenceToC(),那么B对对象C的引用将被消除,但C仍然会引用B。此时C是否有资格进行垃圾收集

我不确定的原因是,由于引用的方向,从B到C再也达不到,这使我认为C有资格进行垃圾收集,但是C仍然引用B的事实让我很反感

所以,如果B取消了对C的引用,C是否有资格进行垃圾收集

编辑: 这个问题被标记为重复问题。我认为我的问题与先前回答的问题之间的主要区别可以总结如下: 以前的问题: A->bc然后从A到B的引用被删除,留下一个bc

我的问题:
然后从B到C的ref被删除,留下了一个B你在技术方面考虑得太多了。垃圾收集被定义为任何能够回收无法访问对象的存储的措施

定义如下:

可访问对象是可以从任何活动线程在任何可能的连续计算中访问的任何对象

定向引用是一种方式,运行代码如何访问对象,事实上,遍历这些引用是垃圾收集器实现检测对象可访问性的典型方式,但必须强调的是,即使存在局部变量,如果没有“潜在的持续计算”读取对象,则引用对象不足以阻止其垃圾收集

实际上,当JVM的优化器转换代码,消除未使用的变量和死代码时,就会发生这种情况

链接部分还明确指出:

可以设计程序的优化转换,以减少可访问对象的数量,使其少于天真地认为可访问的对象的数量


不要因为这些技术细节而分心,只要知道只有访问对象的可能性才与确定它不是垃圾相关就足够了。因此,无论对象如何与引用链接,如果没有活动线程可以访问它们,它们都是垃圾。

“然而,C仍然引用B的事实让我很反感。”为什么?重要的是是否存在对某个对象的引用,而不是该对象本身引用的位置。重要的是是否可以从GC根访问某个对象:@Tom我的想法是,有一个箭头从B指向C,另一个箭头从C指向B,每个箭头都表示一个引用。如果我将B对C的引用置空,我将移除从B到C的箭头,但是从C到B的箭头仍然保留(但它指向C到B)。所以,当垃圾收集器执行其任务时,它是否认为C仍然可以从B访问?或者它是否看到一个从C指向B的“箭头”,并意识到C无法从B访问?引用是“定向的”-如果您将
B
置空,则无法从B访问C。如果你不能访问它,根据定义,它是不可访问的。C指向B并不重要,这并不能帮助B找到C。问问自己:
C
仍然可以从
B
访问吗?如果不是,为什么某人或某物会这样认为?您“
null
ed”变量,这也是“触发”删除对象的常用方法,因为没有变量仍然引用该对象。