Frage zur Garbage Collection in Java

8

Angenommen, ich habe eine doppelt verknüpfte Liste. Ich erstelle es als solches:

%Vor%

Dann füge ich einige Knoten hinzu, verwende sie und entscheide mich dann, die alte Liste wie folgt wegzuwerfen:

%Vor%

Da ich gerade eine neue Liste erstellt habe, zeigen die Knoten innerhalb des alten Speicherbereichs immer noch zueinander. Bedeutet das, dass die Region mit den alten Knoten keinen Müll sammelt? Muss ich jeden Knotenpunkt auf Null stellen, damit sie GC'd sind?

    
captain poop 17.08.2010, 19:43
quelle

7 Antworten

12

Nein, das tust du nicht. Der Java GC behandelt zyklische Referenzen einfach.

Im Prinzip betrachtet jedes Mal, wenn der GC läuft, alle "lebenden" Wurzelreferenzen im System:

  • Lokale Variablen in jedem Stapelrahmen
  • "this" verweist in jedem Fall auf den Stack-Frame
  • Effektiv, alle statischen Variablen (Tatsächlich werden diese tatsächlich von Class -Objekten referenziert, auf die wiederum ClassLoader s verweist, die wir aber im Moment ignorieren können.)

Mit diesen "bekannten Live" -Objekten untersucht es die Felder in ihnen und fügt sie der Liste hinzu. Es rezeriert in diese referenzierten Objekte und so weiter, bis es jedes Live-Objekt im System gefunden hat. Dann sammelt Müll alles, was er nicht als lebend empfunden hat.

Ihre zyklisch referenzierten Knoten verweisen aufeinander, aber kein Live-Objekt verweist auf sie. Daher sind sie für die Garbage Collection geeignet.

Beachten Sie, dass dies eine grob vereinfachte Zusammenfassung der Funktionsweise eines Garbage Collector ist . In Wirklichkeit sind sie sehr kompliziert, mit Generationen, Komprimierung, Nebenläufigkeit und dergleichen.

    
Jon Skeet 17.08.2010, 19:46
quelle
1

Wenn Sie Ihre eigene doppelt verkettete Liste erstellt haben und diese doppelt verknüpfte Liste Container (die Elemente aus Ihrer Liste enthalten) eingeben; Nur diese Container sind miteinander verbunden.

Also in Ihrer Liste haben Sie ein Objekt A in A 'enthalten. A 'ist mit B verbunden und B' ist ein Container, der B usw. enthält. Und keines der Objekte muss sich auf ein anderes beziehen.

Im Normalfall sind diese Container nicht von außen verfügbar (nur der Inhalt ist interessant); Daher enthält nur Ihre Liste Verweise auf Ihre Container (denken Sie daran, dass Ihr Inhalt seinen Container nicht kennt).

Wenn Sie Ihre letzte Referenz auf Ihre Liste (die Liste, nicht den Container oder den Inhalt) entfernen, wird der GC versuchen, Ihre Listeninhalte zu sammeln, also Ihre Container und Ihre Inhalte.

Da Ihre Container außerhalb der einzigen Referenz, die sie haben, nicht verfügbar sind, ist sie eine und die Hauptliste. All dies wird als Insel der Isolation bezeichnet. Betreffend den Inhalt, wenn sie noch Verweise in deiner Anwendung haben, werden sie den GC überleben, wenn nicht, werden sie nicht.

Wenn Sie also Ihre Liste entfernen, werden nur A 'und B' gelöscht, da diese Referenzen selbst dann, wenn sie noch Referenzen haben, Teil einer Insel sind. Wenn A und B keine Referenzen mehr haben, werden sie ebenfalls gelöscht.

    
Colin Hebert 17.08.2010 20:00
quelle
0

Nein - Java (zumindest wie normalerweise implementiert) verwendet keine Referenzzählung, es verwendet einen echten Garbage Collector. Das bedeutet (im Wesentlichen), wenn es keinen Speicher mehr hat, die Zeiger auf dem Stack, in Registern und anderen Orten, auf die immer zugegriffen werden kann, und "jagt" sie, um alles zu finden, auf das sie zugreifen können.

Zeiger in anderen Datenstrukturen wie Ihrer doppelt verknüpften Liste sind einfach egal, es sei denn, es gibt einen äußeren Zeiger (der zugänglich ist), der zu ihnen führt.

    
Jerry Coffin 17.08.2010 19:49
quelle
0

Nein, der GC wird sie trotzdem zurückfordern, sodass Sie sie nicht auf null setzen müssen. Hier ist eine gute Absatzbeschreibung aus diesem JavaWorld Artikel :

  

Jeder Garbage-Collection-Algorithmus muss   zwei grundlegende Dinge tun. Zuerst muss es   Müllobjekte erkennen. Zweitens, es   muss den von. verwendeten Heap-Space zurückfordern   die Müllobjekte und mach es   verfügbar für das Programm. Müll   die Erkennung wird normalerweise durchgeführt   durch Definieren einer Menge von Wurzeln und   Bestimmen der Erreichbarkeit aus der   Wurzeln. Ein Objekt ist dort erreichbar   ist ein Weg der Referenzen von der   Wurzeln, durch die das ausführende Programm   kann auf das Objekt zugreifen. Die Wurzeln sind   immer zugänglich für das Programm. Irgendein   Objekte, die von der erreichbar sind   Wurzeln gelten als leben. Objekte   die nicht erreichbar sind, werden berücksichtigt   Müll, weil sie nicht mehr können   beeinflussen den zukünftigen Verlauf des Programms   Ausführung.

    
Taylor Leese 17.08.2010 19:50
quelle
0

Der Garbage Collector prüft, ob Objekte von Live-Threads referenziert werden. Wenn Objekte von Live-Threads nicht erreichbar sind, sind sie für die Garbage Collection geeignet.

Es spielt keine Rolle, ob die Objekte sich gegenseitig referenzieren.

    
Jesper 17.08.2010 19:50
quelle
0

Wie andere bereits erwähnt haben, betrachtet der Java-Garbage Collector nicht einfach die Referenzzählung. Stattdessen betrachtet es im Wesentlichen ein Diagramm, in dem die Knoten die Objekte sind, die derzeit existieren, und Verknüpfungen eine Referenz von einem Objekt zu einem anderen sind. Es beginnt mit einem Knoten, von dem bekannt ist, dass er live ist (zum Beispiel die Hauptmethode), und dann sammelt der Müll alles, was nicht erreicht werden kann.

Der Wikipedia-Artikel über Garbage Collection diskutiert eine Vielzahl von Möglichkeiten, wie dies getan werden kann, obwohl ich nicht weiß nicht genau, welche Methode von einer der JVM-Implementierungen verwendet wird.

    
Scott 17.08.2010 20:00
quelle
-1

Der Garbage Collector sucht nach Objekten, auf die nirgendwo verwiesen wird. Also, wenn Sie ein Objekt erstellen und Sie die Referenz wie das Beispiel verlieren, sammelt der Garbage Collector das.

    
Daniel Moura 17.08.2010 19:48
quelle

Tags und Links