© DrHitch/Shutterstock.com
Memory Leaks in Java

2 Akkumulation oder: Wenn Leaks sich läppern


Im vorangegangenen Kapitel [1] hatten wir uns die konkrete Implementierung eines Servers angesehen, der ein Memory Leak hatte, das zu einem OutOfMemoryError führen konnte. Dieses Mal wollen wir detailliert die Mechanismen diskutieren, die allgemein ein Memory Leak und einen daraus resultierenden OutOfMemoryError verursachen.

Als Beispiel für ein Memory Leak haben wir uns beim letzten Mal die Implementierung eines rudimentären Servers auf Basis der mit Java 7 eingeführten AsynchronousSocketChannels angesehen. Das Memory Leak entstand dadurch, dass wir für jeden Client Verwaltungsinformation (die ClientSession) in einer Map gespeichert haben und diese clientspezifischen Map-Einträge nicht nach der Beendigung der Kommunikation mit den jeweiligen Clients wieder gelöscht haben. Dadurch vergrößert sich die Map mit jedem neuen Client. Erzeugt man dann in einem Testprogramm genügend viele Clients hintereinander, so stürzt der Server mit einem OutOfMemoryError ab. Der Sourcecode zu dem Beispiel sowie verschiedene alternative Korrekturen, die wir im vorherigen Kapitel besprochen haben, finden sich unter [2].

Ungewollte Referenzen

Rufen wir uns noch einmal in Erinnerung, wie es genau zu einem Memory Leak kommt. Der Garbage Collector ermittelt ausgehend von so genannten Root References, welche Objekte in einem Java-Programm referenziert und damit erreichbar sind. Alle nicht erreichbaren Objekte räumt der Garbage Collector bei der Garbage Collection weg und gibt ihren Speicher frei. Wenn wir nun auf ein Objekt verweisen, von dem wir sicher sagen können, dass wir es im weiteren Kontext unseres Programms gar nicht mehr benutzen werden, haben wir ein Memory Leak. Denn das nicht mehr benötigte Objekt wird vom Garbage Collector nicht weggeräumt, weil es noch referenziert wird. Diese Referenz wird in der englischsprachigen Fachliteratur unwanted reference (also: ungewollte Referenz) genannt.

Übertragen wir diese Beschreibung auf unser Memory-Leak-Beispiel vom vorherigen Kapitel: Die clientspezifischen Verwaltungsdaten werden auch nach der Beendigung der Kommunikation mit dem Client weiter über die Map referenziert, sodass der Garbage Collector sie nicht freigeben kann. Die Map mit ihrer internen Datenstruktur bildet also unsere ungewollte Referenz auf die clientspezifischen Daten.

Akkumulation von Leaks führt zu OutOfMemoryError

Eine ungewollte Referenz allein führt noch nicht zu einem problematischen Memory Leak. Noch ein zweiter Aspekt ist wichtig, damit es zu einem OutOfMemoryError aufgrund eines Memory Leaks kommt. Der Programmalgorithmus muss so fehlerhaft sein, dass mit dem weiteren Ablauf immer mehr Objekte über ungewollte Referenzen erreichbar sind. Das ist in unserem Beispiel gegeben: Immer, wenn wir die Kommunikation mit einem Client beenden, „vergessen“ wir dessen Verwaltungsdaten in der Map. Die Anzahl der „geleakten“ Objekte kann also beliebig anwachsen.

Typisch für Memory Leaks, die zu OutOfMemoryError führen, ist der Umstand, dass sie nicht durch einzelne Referenzen wie Stack-Variablen oder Felder von Referenztypen entstehen, sondern durch Akkumulation von Referenzen. So kann eine einzelne Stack-Variable von einem Referenztyp, die wir ganz zu Anfang in der main-Methode angelegt haben, zwar eine ungewollte Referenz sein, aber sie führt nicht zu einem OutOfMemoryError. Der Code für eine solche Situation kann zum Beispiel so aussehen wie in Listing 2.1.

 public static void main(String argv[]) {
String argMsg = "first argument: " + argv[0];
System.out.println(argMsg); //2

// der Rest des Programms, das noch lange laeuft

}

Listing 2.1

Nach dem println() in Zeile //2 wird der über argMsg referenzierte String nicht mehr genutzt. Die Referenz argMsg ist also eine ungewollte Referenz, weil sie ab einem bestimmten Zeitpunkt im Programmablauf auf ein Objekt zeigt, das nicht mehr genutzt wir...

Neugierig geworden? Wir haben diese Angebote für dich:

Angebote für Teams

Für Firmen haben wir individuelle Teamlizenzen. Wir erstellen Ihnen gerne ein passendes Angebot.

Das Library-Modell:
IP-Zugang

Das Company-Modell:
Domain-Zugang