2014-09-30 2 views
0

Пример кода:разрушения объекта, когда дочерний объект ссылается на родительский объект

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; 
    } 
} 

Из того, что я понимаю из жизненного цикла объекта, если объект не должны были быть больше не ссылается, то он будет иметь право на дс, например, когда ссылка на ребенка была изменена для ссылки на новый второй дочерний объект.

Но что, если каждый объект Child имеет ссылку на объект, который его создал, как и выше, будет ли он иметь право на gc в этом случае, если он больше не ссылается на его родительский объект?

Если нет, как я могу написать это так, чтобы это было?

ответ

0

Если экземпляр класса A имеет ссылку на экземпляр класса B, и этот экземпляр класса B имеет ссылку на тот же экземпляр класса A, оба они не будут иметь права на GC, если эти ссылки существуют.

BTW, в вашем примере экземпляр Child присваивается локальной переменной метода внутри класса Parent, поэтому, как только этот метод будет выполнен, экземпляр Child будет иметь право на GC, независимо от того, содержит ли он ссылку к экземпляру родителя, который его создал.

Теперь, если вы сохранили ссылку экземпляра Child в члене класса Parent, у вас будет круговая ссылка. Затем, если код, который хранит экземпляр родителя, теряет все ссылки на экземпляр родителя, циклические ссылки никогда не могут быть удалены, поэтому оба объекта не будут иметь право на GC.

Рассмотрим exmaple:

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, так что в конечном итоге запустить из памяти ,

+0

О да, я сделал опечатку с этим новым родителем(), я отредактировал. Но как бы удалить ссылку на родительский экземпляр из дочернего класса? должен ли я сделать метод removeParent, и внутри он помещает родительскую ссылку в null? – Imp

+0

В приведенном выше примере родитель не имеет ссылки на Child; одна переменная children является локальной переменной внутри метода someMethod(). – Marco

+0

@Nonexistent Если у вас есть ссылка на экземпляр Child, и у вас есть метод в классе Child, который обнуляет ссылку Parent, вы можете очистить эту ссылку. Но если у вас нет ссылки на экземпляр Child, вы не сможете этого сделать. – Eran

0

В вашем someMethod(), возможно создание двух экземпляров со значением Child; тот факт, что они оба относятся к одному и тому же Parent, не имеет никакого отношения к тому факту, что первый экземпляр, который вы создали, будет (в конечном итоге) GC'd после того, как он будет удален (если вы повторно назначите переменную child и создадите новую экземпляр объекта Child).

На практике это не так быстро - процесс GC проходит через несколько этапов (вы можете узнать о фазах Tenured, Eden и Survivor).

0

По this answer:

GC в Java рассматривает объекты «мусор», если они не доступны через цепного начиная с корнем сбора мусора, так что эти объекты будут быть собраны. Даже если объекты могут указывать друг на друга, чтобы сформировать цикл , они все еще мусор, если они отрезаны от корня.

Так что вам не нужно ничего делать для этого циклического эталона.

Смежные вопросы