Java 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.
Weiterlesen »