2013-05-16 11 views
12

Przeczytałem niektóre przewodniki po śmieciach w Internecie, ale nadal jestem trochę niejasny i chciałem się upewnić, że nie mam przecieków pamięci w moim kodzie.Czy Java GC niszczy obiekty, jeśli zmienne instancji nadal mają odniesienie?

Czy Java GC zbiera obiekty, które utraciły swoje odniesienie, ale jego zmienne nadal mają odniesienie?

Więc powiedzmy, że mam SomeObject:

public class SomeObject { 
    public ObjectVar var; 

    public SomeObject() { 
     var = new ObjectVar(); 
    } 
} 

A mój kod:

SomeObject obj1 = new SomeObject(); 
SomeObject obj2 = new SomeObject(); 
obj2.var = obj1.var; 
obj1 = null; 

Więc obj1 za var ma odniesienie, ale obj1 nie ma już żadnego odniesienia. Czy GC zniszczy obj1, ale zachowa var żywy? (Zakładam, że tak, po prostu chciałem się upewnić). Dzięki!

+0

Podstawową regułą dla GC jest to, że jeśli GC'ing obiekt wpłynie na twój program, tak się nie stanie. (O ile nie używasz specjalistycznych narzędzi dbających o GC, ale jeśli używasz tego, będziesz wiedział.) –

+0

Możesz przeczytać o ["Kryzys wieku średniego"] (http: //blogs.msdn. com/b/ricom/archive/2003/12/04/41281.aspx). – Mehrdad

Odpowiedz

12

Oto co się wydarzy (patrz komentarze poniżej)

// obj1 and obj1.var get created 
SomeObject obj1 = new SomeObject(); 
// obj2 and obj2.var get created 
SomeObject obj2 = new SomeObject(); 
// old obj2.var becomes eligible for GC 
obj2.var = obj1.var; 
// obj1 becomes eligible for GC 
obj1 = null; 

W końcu, dwa obiekty, które nie pozostają dostać GCD - obj2 i byłego obj1.var który jest obecnie określanej jako obj2.var.

Uwaga: W szczególnym przypadku ObjectVar klasa bycia non-static wewnętrzna klasa SomeObject, utrzymując odniesienie do obj1.var również zachować obj1 dookoła. Dzieje się tak, ponieważ wewnętrznie klasa SomeObject.ObjectVar ma ukrytą zmienną typu SomeObject, która odwołuje się do zewnętrznego obiektu wewnętrznej klasy.

+0

Ok dzięki! Ale teraz jestem zdezorientowany, ponieważ dwie osoby mają różne odpowiedzi. Jeśli obiekt ObjectVar był podklasą (lub klasą wewnętrzną) obiektu SomeObject, powyższy kod spowoduje, że obiekt obj1 będzie nieodpowiedni dla GC? – baekacaek

+1

Komentarz @baekacaek ZyyaoWei rozpatrywał tylko statyczne klasy wewnętrzne, w tym przypadku nie ma to znaczenia. Niestatyczne klasy wewnętrzne i anonimowe lub nazwane metody - klasy lokalne mogą sprawić, że obiekt hosta nie zostanie zbufowany, ale statyczne klasy wewnętrzne nie. – dasblinkenlight

+0

Jeszcze raz dziękuję za wyjaśnienia i szybkie odpowiedzi! – baekacaek

3

Tak, oczywiście.

Pamiętaj, że to, co przechowujesz w polu var, jest w rzeczywistości odniesieniem do obiektu, a nie samego obiektu. Więc kiedy GC zbiera obj1, obiekt var jest nietknięty (nie wolno dotykać), zwłaszcza, że ​​ma odwołanie od obj2, który jest wciąż żywy i dobrze ..

+0

Dzięki, czy to samo ma zastosowanie, jeśli ObjectVar jest wewnętrzną klasą SomeObject? – baekacaek

+0

Cóż, to nie powinno mieć znaczenia, ponieważ bez względu na to, co obj2 ma odniesienie do tego obiektu. –

+2

Jeśli jest to statyczna wewnętrzna klasa, to nie ma to znaczenia. Jednakże, gdy jest to niestatyczna klasa wewnętrzna, 'var' ma" odwołanie zwrotne "do zewnętrznej klasy, co może utrzymać właściciela przy życiu dłużej niż można by oczekiwać. – dasblinkenlight

0

Tak - zachowanie jest takie, jak opisujesz. Ogólna zasada usuwania śmieci polega na tym, że obiekty kwalifikują się tylko wtedy, gdy nie można ich uzyskać poprzez żadne twarde odniesienie. Wszelkie obiekty, do których można dotrzeć w ten sposób, nigdy nie zostaną zebrane jako śmieci (z wyjątkiem miękkich/słabych odniesień).

0

Mówiąc prościej, jeśli obiekt jest nadal dostępny na drodze referencji, gwarantuje się przetrwanie kolekcji. Jeśli nie ma takiej ścieżki, obiekt nie może być już dostępny i można go bezpiecznie zebrać.

Po pierwszych dwóch liniach, pamięć wygląda następująco:

o1 --> SomeObj#1 --> ObjectVar#1 
o2 --> SomeObj#2 --> ObjectVar#2 

Wszystkie 4 obiekty mogą zostać osiągnięte, jeśli zbiór śmieci miały pojawić się w tym czasie żaden z nich nie byłyby zbierane.

Po 3. kolejce, wygląda to tak:

o1 --> SomeObj#1 --> ObjectVar#1 
        ^
o2 --> SomeObj#2 ----- ObjectVar#2 

Teraz tylko 3 przedmioty mogą zostać osiągnięte; śmieciarz może usunąć ObjectVar # 2.

Po 4. kolejce, wygląda to tak:

o1  SomeObj#1 --> ObjectVar#1 
        ^
o2 --> SomeObj#2 ----- ObjectVar#2 

Tylko dwa obiekty są nadal osiągalny; śmieciarz może usunąć SomeObj # 1 i ObjectVar # 2, ale musi zachować SomeObj # 2 i ObjectVar # 1.

Powiązane problemy