Circular References in Java

Biorąc pod uwagę agregację instancji klas, które odnoszą się do siebie w złożony, okrągły sposób: czy możliwe jest, że garbage collector nie będzie w stanie uwolnić tych obiektów?

Mgliście przypominam sobie, że był to problem w JVM w przeszłości, ale myślałem, że to zostało rozwiązane lata temu. jednak niektóre śledztwo w jhat ujawniło, że okrągłe odniesienie jest powodem wycieku pamięci, z którym mam teraz do czynienia.

Uwaga: zawsze byłem pod wrażenie, że JVM był w stanie rozwiązywać koliste odniesienia i uwalniać takie "Wyspy śmieci" z pamięci. Jednak zadaję to pytanie tylko po to, aby sprawdzić, czy ktoś znalazł jakieś wyjątki.

Author: Ryan Delucchi, 2008-10-07

10 answers

Tylko bardzo naiwna implementacja miałaby problem z odniesieniami kołowymi. Wikipedia ma dobry Artykuł na temat różnych algorytmów GC. Jeśli naprawdę chcesz dowiedzieć się więcej, spróbuj (Amazon) Garbage Collection: Algorithms for Automatic Dynamic Memory Management . Java ma dobry garbage collector od 1.2 i wyjątkowo dobry w 1.5 i Java 6.

Najtrudniejszą częścią poprawy GC jest redukcja pauz i napowietrznych, a nie podstawowe rzeczy, takie jak okrągłe Referencja.

 41
Author: David G,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-07 00:18:52

Garbage collector wie, gdzie znajdują się obiekty root: statyki, locals na stosie itp., a jeśli obiekty nie są osiągalne z katalogu root, zostaną odzyskane. Jeśli są osiągalne, muszą zostać.

 22
Author: Rob Walker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-07 00:02:47

Ryan, sądząc po twoim komentarzu do Circular References in Java, wpadłeś w pułapkę odwoływania się do obiektów z klasy, która prawdopodobnie została załadowana przez Bootstrap/system classloader. Do każdej klasy odwołuje się classloader, który załadował tę klasę, A więc może być zbierany tylko wtedy, gdy classloader nie jest już osiągalny. Haczyk polega na tym, że Bootstrap / system classloader nigdy nie jest zbierany jako śmieci, dlatego obiekty osiągalne z klas załadowanych przez system classloader również nie może być zbierany.

Uzasadnienie takiego zachowania jest wyjaśnione w JLS. Na przykład trzecia edycja 12.7 http://java.sun.com/docs/books/jls/third_edition/html/execution.html#12.7 .

 12
Author: Alexander,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:32:04

Jeśli dobrze pamiętam, to zgodnie ze specyfikacją istnieją tylko gwarancje tego, czego JVM nie może zebrać (cokolwiek osiągalnego), a nie tego, co zbierze.

O ile nie pracujesz z JVMs w czasie rzeczywistym, większość nowoczesnych śmieciarek powinna być w stanie obsłużyć złożone struktury odniesienia i zidentyfikować "podgrafy", które można bezpiecznie wyeliminować. Wydajność, opóźnienie i prawdopodobieństwo tego poprawy w miarę upływu czasu coraz więcej pomysłów badawczych trafia do standardowe (a nie badawcze) maszyny wirtualne.

 4
Author: Uri,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-07 00:35:31

Nie, przynajmniej używając oficjalnego JVM Sun ' a, garbage collector będzie w stanie wykryć te cykle i zwolnić pamięć, gdy tylko nie będzie już żadnych odniesień z zewnątrz.

 3
Author: Thilo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-07 00:02:55

Specyfikacja Java mówi, że garbage collector może śmieci zbierać swój obiekt Tylko wtedy, gdy jest nieosiągalny z żadnego wątku.

Osiągalny oznacza, że istnieje odniesienie lub łańcuch odniesień, który prowadzi od A do B, i może przejść przez C, D,...Z jak dla mnie.

JVM nie zbiera rzeczy nie był dla mnie problemem od 2000 roku, ale twój przebieg może się różnić.

Wskazówka: serializacja Java buforuje obiekty, aby transfer siatki obiektów był efektywny. Jeśli masz wiele dużych, przejściowych obiektów, a cała twoja pamięć zostaje zablokowana, zresetuj serializer, aby wyczyścić pamięć podręczną.

 3
Author: Tim Williscroft,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-07 00:27:24

Aby wzmocnić to, co już zostało powiedziane:

Aplikacja, nad którą pracuję od sześciu lat, zmieniła się ostatnio z Javy 1.4 na Javę 1.6 i odkryliśmy, że musieliśmy dodać statyczne odniesienia do rzeczy, o których wcześniej nawet nie wiedzieliśmy, że są zbierane. Wcześniej nie potrzebowaliśmy statycznego odniesienia, ponieważ garbage collector był do bani, a teraz jest o wiele lepiej.

 2
Author: Paul Tomblin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-07 00:10:54

Indeksowanie GCs jest notoryczne z tego problemu. Warto zauważyć, że Suns JVM nie używa referencji liczącej GC.

Jeśli obiekt nie może dotrzeć do korzenia sterty (zazwyczaj, co najmniej, przez classloadery, jeśli nic nie jest else0, to obiekty zostaną zniszczone, ponieważ nie są kopiowane podczas typowego Java Gc do nowej sterty.

 2
Author: Will Hartung,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-07 00:20:52

Okrągłe odniesienie ma miejsce, gdy jeden obiekt odnosi się do drugiego, a drugi odnosi się do pierwszego obiektu. Na przykład:

class A {
private B b;

public void setB(B b) {
    this.b = b;
}
}

class B {
private A a;

public void setA(A a) {
    this.a = a;
}
}

public class Main {
public static void main(String[] args) {
    A one = new A();
    B two = new B();

    // Make the objects refer to each other (creates a circular reference)
    one.setB(two);
    two.setA(one);

    // Throw away the references from the main method; the two objects are
    // still referring to each other
    one = null;
    two = null;
}
}

Moduł garbage collector Javy jest wystarczająco inteligentny, aby wyczyścić obiekty, jeśli istnieją odniesienia okrągłe, ale nie ma już aktywnych wątków, które mają odniesienia do obiektów. Tak więc posiadanie takiego okrągłego odniesienia nie powoduje wycieku pamięci.

 2
Author: Rupesh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-01 17:25:18

Garbage collector to bardzo wyrafinowany program, który został przetestowany w ogromnym pakiecie testowym JCK. Nie jest to idealne rozwiązanie, ale jest bardzo duża szansa, że tak długo, jak kompilator java (javac) skompiluje wszystkie Twoje klasy i JVM utworzy instancję, to powinieneś być dobry.

Z drugiej strony, jeśli posiadasz odwołania do głównego grafu obiektu, pamięć nie zostanie zwolniona, ale jeśli wiesz, co robisz, powinno być OK.

 0
Author: anjanb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-07 00:02:54