代码示例:
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? 如果没有,我该如何写它呢?
答案 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阶段)。