Java Memory-Leaks mit plumbr finden
Java, Web Entwicklung April 2nd, 2013Java hat einen schlechten Ruf, auch heute noch: Langsam, braucht zu viel Speicher, umständlich und und und. Das mit dem Speicher ist bei Java gerade bei Webanwendungen (oder Enterprise-Anwendungen) wirklich so eine Sache. Bei nicht wenigen Projekten habe ich gesehen, dass Java Server (Tomcat, Websphere, …) Nachts regelmäßig durchgestartet werden, um dafür zu sorgen, dass es keine Speicherprobleme gibt.
Die Speicherprobleme kommen jedoch nicht von Java selbst, sondern es handelt sich in der Regel um Memory-Leaks. Diese können auch bei manueller Speicherverwaltung (malloc/free vs. Garbage Collection bei Java) auftreten. Eine ganz besondere Form von Speicherlecks sind sogenannte „Permgen-Leaks“. Permgen ist der Speicherbereich der Sun/Oracle Hotspot VM in der z.B. Java Klassen gehalten werden. Solange diese gebraucht werden, bleiben die Klassen geladen. Klassen gehören zu einem Classloader, eine Klasse, die von verschiedenen Classloadern geladen wurde, stellt sich der Anwendung in der Regel als verschiedene Klassen dar. Die damit einhergehenden Probleme wenn das innerhalb der selben Anwendung passiert können nochmal ganz andere sein.
Bei Web-Anwendungen gibt es einen Classloader, der für eine deployte (oder deutsch „verteilte“, „zur Verfügung gestellte“) zuständig ist. Wird die Anwendung undeployt, jedoch der Container (Tomcat z.B.) nicht heruntergefahren sollte dennoch der Speicher der Anwendung, insbesondere auch der Permgen Speicher, wieder freigegeben werden.
Passiert das nicht, führt das unweigerlich nach mehreren Re-Deployments zu einem „Out of Memory: Permgen“ Problem.
Aus diesem Grund werden dann oft die Server zusammen mit dem Deployment neu gestartet. Das kann Zeit kosten und ist in meinen Augen die Garantie dafür, dass die Speicherlecks auch dauerhaft nicht behoben werden: Die Entwickler spüren die Schmerzen nicht, das senkt die Motivation etwas zu tun. Bewegt man sich in Richtung Continuous-Integration oder gar Continuous-Deployment kommt ständiges Neustarten von Servern nicht in Frage: Es dauert lange, Caches sind danach kalt.
Bisher habe ich Speicherlecks daher stets gejagt: VisualVM (Sun/Oracle, Teil des JDK), Eclipse MAT (SAP Entwicklung, OpenSource) oder auch YourKit (Profiler, kommerziell) und findbugs (OpenSource) haben mir gute Dienste geleistet. Kommt man ohne EAR aus, hilft auch der in Tomcat integrierte Memory-Leaks-Prevention-Listener, ähnliches bietet auch Jetty. Nicht immer hat man reines WAR deployment oder nur Java Servlets, und die manuelle Suche kann sehr zeitintensiv werden.
Seit einiger Zeit gibt es ein Tool aus Estland, dass die Automatisierung von Java Memory-Leaks auf seinen Fahnen stehen hat: Plumbr. Eine kurze Evaluation des Tools an einem konkreten Java Permgenleak dass durch Redeployments einer Spring basierten Webanwendung offensichtlich wurde war sehr vielversprechend. Schnell hatte Plumbr ein Java Speicherleck bei dem verwendeten MySQL Treiber ausgemacht. (Bug http://bugs.mysql.com/bug.php?id=65909 ) Der Fehler war innerhalb von ca. 20 Minuten behoben und wie man sehen kann, führt auch permanentes redeployment zu keinem Problem mehr:
Wer Plumbr ausprobieren will, findet mehr Informationen auf http://www.plumbr.eu/ – in jedem Fall ist dieser Blogartikel fuer Java Entwickler im Enterprise Umfeld lesenswert: http://plumbr.eu/blog/hunting-down-memory-leaks-a-case-study
Java muss nicht speicherhungrig sein. Es ist jedoch für Entwickler erforderlich, ihren Stoff zu kennen und ihr Handwerk zu beherrschen. Tool Unterstützung kann dabei helfen, hier hilft es sehr, wenn man die verschiedenen Werkzeuge kennt und sich kontinuierlich auf dem Laufenden hält.
Neue Kommentare