System.gc() Aufrufe können schwere Folgen haben
1.8.2010 | 2 Minuten Lesezeit
Es passiert jedem Entwickler schon mal, daß man Hinweise aus der JavaDoc nicht besonders Ernst nimmt, oder gar überliest. Insbesondere wenn die angesprochenen Probleme lokal nicht (oder scheinbar nicht) auftreten.
Zum Beispiel aus dem java.text.SimpleDateFormat:
1* Date formats are not synchronized. 2 * It is recommended to create separate format instances for each thread. 3 * If multiple threads access a format concurrently, it must be synchronized 4 * externally.
Vielleicht ist die Warnung auch nicht deutlich genug, dadurch daß dort steht: „It is recommended“.
Deshalb sieht man leider häufig folgende Zuweisung welche zu Nebenläufigkeitsproblemen führen kann
1private static final SimpleDataFormat DATE_FORMAT = new SimpleDateFormat("yyyy.MM.dd");
Schlimmer ist es hingegen bei System.gc().
Dort findet sich keine Warnung im JavaDoc:
1* Calling the gc method suggests that the Java Virtual 2* Machine expend effort toward recycling unused objects in order to 3* make the memory they currently occupy available for quick reuse. 4* When control returns from the method call, the Java Virtual 5* Machine has made a best effort to reclaim space from all discarded 6* objects.
Klingt sogar garnicht so schlecht. Jedoch sollte „suggests“ und „best effort“ einen stutzig machen. Falls man auf die Idee kommt System.gc() zu verwenden prüft man vielleicht was im großen weiten Internet dazu gesagt wird, in der Hoffnung auf Erklärungen zu stoßen was tatsächlich passiert. So finden sich auf Stackoverflow gute Ausführungen . Was es genau tut weiß aber keiner so genau, weshalb diese Anweisung so riskant ist.
Ich finde aber, daß ein Bild mehr sagt als viele Worte:
Wir sehen ein relativ großzügig dimensioniertes System eines unserer Kunden mit 14 GB Heap. Diesem Kunden haben wir geholfen den Speicherverbrauch seiner Anwendung zu reduzieren, jedoch gibt es immer noch Pausenzeiten. Der oben abgebildete Graph stammt aus dem Garbage Collection Log und zeigt die Ursache für die Pausen. Die blaue Kurve unten zeigt Garbage Collection. Doch warum gibt es 13 Garbage Collection Spitzen mit bis zu 35 Sekunden, während die zahlreichen anderen Garbage Collections sehr sehr kurz sind?
Die Antwort liegt in der Ursache für diese 13 Garbage Collections. Sie wurde alle durch ein System.gc() aufgerufen.
Der Aufruf von System.gc() unterbindet damit effektiv die Optimierungsmöglichkeiten der Garbage Collection und schlägt sich auf diesem System in relativ langen Pausenzeiten nieder.
Anmerkung: Dieses System lief auf einer Sun 1.6.0.18 64 bit HotSpot Server VM. Als GC sind -XX:+UseConcMarkSweepGC und -XX:+UseParNewGC konfiguriert. System.gc() liefert keine deterministischen Ergebnisse und muss sich nicht zwangsläufig wie hier beschrieben verhalten. Allerdings beobachten auch andere , daß bei CMS und System.gc() auf jeden Fall ein Full GC durchgeführt wird.
Sollte man im eigenen Code keine System.gc() Aufrufe finden, so verstecken sich diese in genutzten Bibliotheken. Unterbinden kann man sie aber über das Server Argument „-XX:+DisableExplicitGC“. Dieses Argument wird von SUN/Oracle empfohlen.
Weitere Beiträge
von Fabian Lange
Dein Job bei codecentric?
Jobs
Agile Developer und Consultant (w/d/m)
Alle Standorte
Weitere Artikel in diesem Themenbereich
Entdecke spannende weiterführende Themen und lass dich von der codecentric Welt inspirieren.
Gemeinsam bessere Projekte umsetzen.
Wir helfen deinem Unternehmen.
Du stehst vor einer großen IT-Herausforderung? Wir sorgen für eine maßgeschneiderte Unterstützung. Informiere dich jetzt.
Hilf uns, noch besser zu werden.
Wir sind immer auf der Suche nach neuen Talenten. Auch für dich ist die passende Stelle dabei.
Blog-Autor*in
Fabian Lange
Du hast noch Fragen zu diesem Thema? Dann sprich mich einfach an.
Du hast noch Fragen zu diesem Thema? Dann sprich mich einfach an.