子对象引用父对象时的对象销毁

时间:2014-09-30 05:06:20

标签: java object garbage-collection

代码示例:

public class Parent{
  public void someMethod(){
    //start of some sort of loop
    Child child = new Child(this);

    //do something
    //replaces reference from old child to new child
    child = new Child(this);
    //repeats loop
  }
}

public class Child{
   Parent parent;
   public Child(Parent parent){
     this.parent = parent;
   }
}

根据我对对象生命周期的理解,如果不再引用某个对象,那么它就有资格获得gc,就像将子引用更改为引用新的第二个Child对象一样。登记/> 但是,如果每个Child对象都引用了创建它的对象,如上所述,一旦它不再被其父对象引用,它是否有资格获得gc? 如果没有,我该如何写它呢?

3 个答案:

答案 0 :(得分:1)

根据this answer

  

如果无法访问对象,则Java会将对象视为“垃圾”   从垃圾收集根开始的链,所以这些对象会   被收集。即使物体可能指向彼此形成一个   如果它们从根部切断,它们仍然是垃圾。

因此,您不需要为此循环引用案例执行任何特殊操作。

答案 1 :(得分:0)

如果A类的实例具有对B类实例的引用,并且B类实例具有对A类相同实例的引用,则只要这些引用存在,两者都不符合GC的条件。 / p>

顺便说一句,在您的示例中,Child实例被分配给Parent类中的本地方法变量,因此一旦该方法完成,Child实例将符合GC的条件,无论它是否包含对创建它的Parent实例。

现在,如果您将Child实例引用存储在Parent类的成员中,那么您将拥有循环引用。然后,如果调用Parent实例的代码丢失了对Parent实例的所有引用,则永远不会删除循环引用,因此两个对象都不符合GC的条件。

考虑这个例子:

public class Parent{
    private Child child;
    public Parent {
        child = new Child(this);
    }

    public static void main (String[] args)
    {
        while (true) {
            parent = new Parent();
        }
    }
}

public class Child{
    Parent parent;
    public Child(Parent parent){
        this.parent = parent;
    }
}

这里,主方法的无限循环将在每次迭代中创建一个永远不符合GC条件的父和子实例,因此最终会耗尽内存。

答案 2 :(得分:0)

someMethod()中,您要创建班级Child的两个实例;它们都引用相同的Parent这一事实与你创建的第一个实例一旦被取消引用(最终)GC(当你重新分配{时)无关{1}}变量,并创建child对象的新实例。

在实践中,它不是那么直接 - GC过程经历了几个阶段(你可能想了解Tenured,Eden和Survivor阶段)。