In vielen JEE-Anwendungen können Sie heute kaum noch auf XML verzichten. Ob in der Konfiguration, in Datenstrukturen oder in Dienstschnittstellen, Sie werden sicherlich eine Reihe von XML-Dateien verwenden. In einem kürzlich durchgeführten Projekt hatten wir mit einer Reihe von externen Diensten zu tun, die eine XML-Schnittstelle verwendeten. Wir wussten nicht, dass wir damit eine potenzielle Zeitbombe in unsere Anwendung eingebaut hatten... Jeder der in unserer Anwendung aufgerufenen XML-Dienste lieferte Daten für denselben Bereich. Anstatt also eine große Anzahl von Java-Klassen zu schreiben oder zu generieren, entschieden wir uns für die Verwendung von XSLT, um die XML-Daten in ein gemeinsames Format umzuwandeln, das wir leicht unmarshallieren konnten. Während der Leistungs- und Belastungstests hat diese Lösung sehr gut funktioniert und keine Anzeichen einer Verschlechterung gezeigt. Jedoch.... Sobald wir in die Produktion gingen, ging der Anwendung nach ein paar Tagen bei einem Heap von 1 GB der Speicher aus. Das war schlimm. Warum haben unsere Leistungs- und Stresstests dies nicht gezeigt? Wir beschlossen, das einzig Vernünftige zu tun und einen Heapdump zu erstellen, sobald die Anwendung Anzeichen von Stress zeigte. Wir begannen mit der Überwachung des Java-Prozesses mit dem Dienstprogramm jstat, das im JDK enthalten ist.
$ jstat -gcutil <processid> 1s 10000 S0 S1 E O P YGC YGCT FGC FGCT GCT 0.00 0.00 99.98 100.00 26.66 2896 119.886 6000 32234.945 32354.831 0.00 0.00 100.00 100.00 26.66 2896 119.886 6001 32234.945 32354.831 0.00 0.00 100.00 100.00 26.66 2896 119.886 6001 32234.945 32354.831 0.00 0.00 100.00 100.00 26.66 2896 119.886 6001 32234.945 32354.831 0.00 0.00 100.00 100.00 26.66 2896 119.886 6001 32234.945 32354.831 0.00 0.00 100.00 100.00 26.66 2896 119.886 6001 32234.945 32354.831 0.00 0.00 100.00 100.00 26.66 2896 119.886 6001 32234.945 32354.831 0.00 0.00 100.00 100.00 26.66 2896 119.886 6002 32240.277 32360.163
Sobald wir sahen, dass der alte Speicherplatz zu 100% ausgelastet war und der Full Garbage Collector nicht in der Lage war, die Dinge zu bereinigen, haben wir einen Heapdump erstellt
$ jmap -dump:format=b,file=/tmp/heap.hprof <processid>
Mit dem Eclipse Memory Analyzer haben wir uns den Heap-Dump angesehen, um herauszufinden, was die Ursache für das Anwachsen unseres Speichers ist. Dies ergab das folgende Bild.
Ein Klick auf den Link "Leak Hunter" im Analyzer zeigte schnell den möglichen Übeltäter. Die XMLReaderManager-Klasse von Xalan hatte irgendwie einen großen Teil des verfügbaren Speichers in Anspruch genommen.
Die Durchsuchung unserer Maven2 pom-Dateien ergab keine explizite Abhängigkeit von Xalan, aber der Abhängigkeitsgraph in der generierten Maven-Site zeigte es als transitive Abhängigkeit an. In einer unserer Abhängigkeiten war xalan-2.6.0 als Abhängigkeit vermerkt. Wenn wir danach googelten, fanden wir schnell heraus, dass es zwei Bugs gegen xalan gab, die genau dieses Problem beschrieben: XALANJ-2178 und XALANJ-2195. Wenn wir uns den Quellcode von Xalan 2.6.0 ansahen, konnten wir das Speicherleck in der Tat deutlich erkennen, während in 2.7.0 ein Update vorgenommen wurde, um zu verhindern, dass die Klasse Referenzen zu lange behält. Aber warum haben unsere Stresstests auf einem ähnlichen Rechner und mit einer ähnlichen Konfiguration dies nicht gezeigt? Die Antwort darauf findet sich auch im XMLReaderManager. Er versucht, den XMLReader in einem ThreadLocal zwischenzuspeichern, so dass er denselben XMLReader an den Thread weitergeben kann, wenn dieser einen neuen anfordert. In einem JEE-System haben Sie jedoch normalerweise Threadpools, die je nach Systemlast zu einem bestimmten Zeitpunkt nach oben oder unten skalieren. In unseren Stresstests simulierten wir nur über einen längeren Zeitraum eine volle Auslastung. Bei dieser Auslastung kam es nicht zu einem Leck bei den XMLReadern, da Threads aus dem ThreadPool wiederverwendet wurden. Hätten wir eine schwankende Last über einen längeren Zeitraum simuliert, hätten wir dies bereits vor der Produktion bemerkt.
Verfasst von

Jeroen van Erp
Unsere Ideen
Weitere Blogs
Contact



