2010-08-17 7 views
8

Angenommen, ich habe eine doppelt verknüpfte Liste. Ich schaffe es als solches:Frage über Garbage Collection in Java

MyList list = new MyList(); 

Dann habe ich einige Knoten hinzufügen, sie verwenden und danach entscheiden, die alte Liste wie diese wegzuwerfen:

list = new MyList(); 

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

+0

mögliches Duplikat von [Wie behandelt Java Garbage Collector die Selbstreferenz?] (Http://stackoverflow.com/questions/407855/how-does-java-garbage-collector-handle-self-reference) –

+0

siehe auch : [Zirkelreferenzen in Java] (http://stackoverflow.com/questions/176745/circular-references-in-java) –

Antwort

12

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

Konzeptionell jedes Mal der GC läuft, sieht es bei allen „live“ root Referenzen im System:

  • Lokale Variablen in jedem Stapelrahmen
  • „diese“ Referenzen in jedem Fall Verfahren Stapeln
  • Rahmen
  • effektiv alle statischen Variablen (in der Tat diese wirklich referenziert werden durch Class Objekte, die von ClassLoader s referenziert wiederum sind, können aber, dass für den Moment ignorieren.)

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 hat, als live zu sein.

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 ist ein grob vereinfachte Zusammenfassung, wie ein Garbage Collector konzeptionell funktioniert. In Wirklichkeit sind sie sehr kompliziert, mit Generationen, Verdichtung, Nebenläufigkeit und dergleichen.

-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, wird der Garbage Collector dies sammeln.

0

Nein - Java (mindestens so normal 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 Stapel, in Registern und anderen Orten, die immer zugänglich sind, und "jagt" sie, um alles zu finden, auf das von ihnen zugegriffen werden kann.

Zeiger in anderen Datenstrukturen wie Ihre doppelt verkettete Liste sind einfach nicht wichtig, es sei denn, es gibt einen äußeren Zeiger (der zugänglich ist), der zu ihnen führt.

0

Nein, der GC wird sie trotzdem zurückfordern, sodass Sie sie nicht auf null setzen müssen. Hier ist ein guter Absatz Beschreibung dieser Javaworld article:

Jede Speicherbereinigungsalgorithmus muss zwei grundlegende Dinge tun. Zuerst muss es Müllobjekte erkennen.Zweitens muss den von verwendeten Speicherbereich freigeben und das Programm für das Programm verfügbar machen. Erkennung erfolgt normalerweise durch Definieren einer Reihe von Wurzeln und Bestimmung Erreichbarkeit von Wurzeln. Ein Objekt ist erreichbar, wenn dort ein Pfad von Referenzen aus den Wurzeln ist, über die das ausführende Programm auf das Objekt zugreifen kann. Die Wurzeln sind immer zugänglich für das Programm. Alle Objekte, die von den Roots aus erreichbar sind, werden als live betrachtet. Objekte , die nicht erreichbar sind, gelten als Müll, weil sie nicht mehr Auswirkungen auf den zukünftigen Verlauf des Programms Ausführung haben können.

0

Der Garbage Collector überprüft, ob Objekte von Live-Threads referenziert werden. Wenn Objekte von keinem Live-Thread erreicht werden können, sind sie für die Garbage Collection geeignet.

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

0

Wie andere darauf hingewiesen haben, schaut der Java Garbage Collector nicht einfach auf 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.

The Wikipedia article on garbage collection diskutiert eine Vielzahl von Möglichkeiten, wie dies getan werden kann, obwohl ich nicht genau weiß, welche Methode von einer der JVM-Implementierungen verwendet wird.

1

Wenn Sie Ihre eigene doppelt verkettete Liste erstellt haben und diese doppelt verkettete 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 den Container nicht kennt).

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

Da Ihre Container nicht verfügbar sind außerhalb der einzigen Referenz, die sie haben, ist einander und die Hauptliste. All dies nennt man eine Insel der Isolation. Wenn sie in Ihrem Antrag noch Referenzen haben, werden sie den GC überleben, wenn nicht, werden sie es nicht tun.

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