2010-01-18 20 views
12

Eine kleine Frage bezüglich der Leistung in einer Java Web App.Java Collections und Garbage Collector

Nehmen wir an, ich habe eine List<Rubrique>listRubriques mit zehn Rubrique Objekte.

Rubrique A enthält eine Liste von Produkten (List<product>listProducts) und eine Liste von Kunden (List<Client>listClients).

Was genau im Speicher passiert, wenn ich dies tun:

listRubriques.clear(); listRubriques = null; 

Mein Standpunkt, dass sein würde, da listRubriques leer ist, alle meine Objekte zuvor von dieser Liste verwiesen wird (einschließlich listProducts und listClients) werden Müll sammelte sich bald. Aber da Sammlung in Java sind ein wenig kompliziert, und da ich mit meiner app ganz Performance-Probleme haben Ich frage die Frage :)

edit: nehmen wir an, jetzt, dass mein Client-Objekt eine List<Client> enthält. Daher habe ich eine Art zirkulären Bezug zwischen meinen Objekten. Was würde dann passieren, wenn mein listRubrique auf null eingestellt ist? Dieses Mal mein Standpunkt wäre, dass meine Client-Objekte werden "unerreichbar" und könnte ein Speicherleck erstellen?

Antwort

14

Die eigentliche Sun-Implementierung für Java kopiert von Zeit zu Zeit alle referenzierten/lebenden Objekte. Der Platz, von dem kopiert wurde, kann dann wieder für die Speicherzuweisung verwendet werden.

Das sagte Ihre Beispiele Schäden tatsächlich Leistung. listRubriques.clear() ist nicht erforderlich (außer Sie halten irgendwo sonst einen Verweis darauf), da alles, auf das readList verweist, leer ist, sobald listRubriques nicht mehr referenziert wird. listRubriques = null kann auch nicht benötigt werden, wenn die Variable listRubriques danach den Gültigkeitsbereich verlässt (möglicherweise weil es eine lokale Variable ist und die Methode hier endet).

Nicht nur der Aufruf zum Löschen ist nicht notwendig, da Clear auf den Speicher des Objekts zugreift, das später nicht mehr verwendet wird, auf das Objekt zugegriffen wird und moderne Prozessoren es in ihren Cache stellen. Ein totes Objekt geht also explizit zum Prozessor-Cache - einige möglicherweise nützlichere Daten werden für diese Operation überschrieben.

This article ist eine gute Referenz, um mehr Informationen über den Java Garbage Collector zu bekommen. EDIT: Um auf die Bearbeitung in der Frage zu reagieren: Der Garbage Collector (die von Sun mindestens verwendete Implementierung) beginnt mit einigen Wurzelreferenzen und kopiert alle Objekte, die er von diesen Referenzen erreichen kann die kopierten Objekte. Daher sind Ihre kreisförmig referenzierten Objekte Müll, da kein "äußerer" Verweis auf sie verweist und der Speicher in der Garbage Collection zurückgewonnen wird.

+0

Vorsicht: Ihr erster Satz beschreibt die aktuelle Implementierung der Sun JVM. Es ist keine Aussage, die im Allgemeinen über Java zutrifft. Der Rest der Antwort scheint allgemein anwendbar zu sein. –

+0

Danke für den Hinweis, ich habe den ersten Satz geändert. – Mnementh

3

Wenn Sie:

listRubriques = null; 

und gibt es keine weiteren Objekte Verweise auf listRubriques oder die darin enthaltenen Objekte, es ist qualifizierten für die Garbage Collection zu halten. Es gibt jedoch keine Garantie dafür, wann die JVM tatsächlich die Garbage Collection ausführen und freien Speicher freigeben wird.Sie können anrufen:

System.gc(); 

die JVM empfehlen, die Sie zu diesem Zeitpunkt der Garbage Collection denken läuft eine gute Idee ist. Aber selbst dann gibt es keine Garantie.

Auch

mit
listRubriques.clear(); 

vor listRubriques zu null Einstellung ist nicht erforderlich.

EDIT: Ihre Frage über zirkuläre Referenzen zu beantworten, JVMs sind intelligent genug, dass das gesamte Objekt Diagramm, um herauszufinden, von jedem aktiv laufenden Code getrennt wird und die JVM korrekt bestimmen, dass sie für die Garbage Collection alle in Betracht kommen. Dies war schon immer in den schlechten Zeiten der Referenzzählung der Fall. Moderne JVMs sind nur schneller und effizienter. Aber sie sammeln keine Objekte mehr als ältere JVMs.

+0

In Bezug auf das Löschen vor der Null habe ich es einfach gemacht, um sicher zu gehen, dass mein Objekt keine Referenzen mehr hat. Aber mir geht es gut, es ist ein nutzloser Doppel-Check. Ich habe gelesen, dass System.gc(); war in alten Java-Versionen nützlich, wird aber heutzutage total ignoriert, oder? – Anth0

+0

@ Anth0: Ich habe das nicht gehört und die J2SE Docs für Java 6 erwähnen nichts dergleichen (http://java.sun.com/javase/6/docs/api/java/lang/System.html #gc()). Für eine maximale Portabilität sollten Sie keine Annahmen über die JVM-Implementierung machen, auf der Ihre App ausgeführt wird. Schauen Sie sich diesen Artikel von Sun für die Wahrheit über die Garbage Collection: http://java.sun.com/docs/books/performance/1st_edition/html/JPAppGC.fm.html – Asaph

+0

Hervorrufen System.gc() wird in der Regel durch neuere vergeben VMs, obwohl nicht garantiert. Wenn Sie die Ausführung des GC anfordern, obwohl dies nicht erforderlich ist, können Sie jedoch möglicherweise ein Leistungsproblem erstellen und dieses Problem nicht lösen. – jarnbjo

1

"Ziemlich bald" ist eine ziemlich vage Spezifikation, aber der Müllsammler ist wahrscheinlich nicht so schnell, wie Sie zu erwarten scheinen. Ob die Objekte tatsächlich erfasst werden, hängt stark von der GC-Konfiguration und der Serverlast ab, aber es kann eine Weile dauern. Wenn Ihre VM genügend Heap zur Verfügung hat und andere Dinge zu tun sind, werden die Objekte nicht "ziemlich bald" gesammelt. .

Die einzige Situation, in der die VM-Spezifikation garantiert, dass der GC ausgeführt wird, ist, wenn an einem anderen Punkt ein OutOfMemoryError geworfen würde. Bevor ein OutOfMemoryError geworfen wird, muss die VM versuchen, mindestens so viele geeignete Objektinstanzen zu sammeln, dass die entsprechende Speicherzuweisungsanforderung erfolgreich ausgeführt werden kann (Sie können jedoch nicht garantieren, dass alle berechtigten Instanzen erfasst werden).

Verwandte Themen