Als Systemadministrator und Betreiber von Java-Server-Applikationen sollte man das Innere des Java Garbage Collectors ansatzweise verstehen.
Gerade bei Applikationen die einen großen Speicherbedarf haben (Daten im Arbeitsspeicher halten um sie schneller ausliefern zu können) sollte man sich überlegen ob der Standardcollector der Richtige ist.
Die JVM entscheidet anhand diverser Systemkennzahlen (ab einer bestimmten Anzahl von RAM und CPUs/Cores meint die JVM auf einem Serversystem zu laufen und nicht auf einem Desktop) welche Standardcollectoren verwendet werden.
Der Speicher für die Objekte wird in einem Heap verwaltet. Dieser ist in den meisten Collectoren unterteilt in mehrere sogenannten Spaces.
- Eden Space
- Survivor Space (davon gibt es 2)
- Old Generation
Stark vereinfacht werden alle neuen Objekte im Eden Space erzeugt. Sollte ein neues Objekt nicht in den Eden-Space passen, dann wird es direkt in der Old Generation abgelegt.
Im Survivor Space befinden sich diejenigen Objekte, die sich vorher im Eden Space befanden und mindestens eine Garbage Collection überlebt haben.
In Old Generation befinden sich die langlebigsten Objekte. Und zwar i.d.R. diejenigen, die mehrere Garbage Collection Durchläufe im Survivor Space überlebten.
In Permanent Generation (Non Heap) speichert die JVM (vereinfacht) diejenigen Objekte, die keiner besondere Garbage Collection bedürfen (z.B. Klassen, Code, sonstiger Java Overhead..)
Je nach Space und Plattform (Server oder Desktop) wird ein anderer Algorithmus für die Garbage Collection verwendet. Dabei werden in der Regel die Eden und Survivor Spaces frequentierter und schneller von Garbage befreit. Während im Old Generation Space der GC seltener, aber dafür länger, sein Werk vollbringt.
Je nach Anwendung (Desktop oder Serverapplikation, schnelles GC aber mit längerer Programmunterbrechung, concurrent GC mit kürzeren Programmunterbrechungen aber dafür mehr CPU und Speicherverbrauch für den GC Vorgang, schnelles Allokieren von neuem Speicher [keine Speichfragmentierungen im Heap]) lohnt es sich den Garbage Collector auf den jeweiligen passenden Algorithmus (sofern dies Java noch nicht automatisch getan hat) umzustellen.
U.a. stehen die folgenden Garbage Collector Algorithmen zur Auswahl (sie können mittels Parameter der JVM übergeben und konfiguriert werden):
- Serial Collector
- Parallel Collector
- Parallel Compacting Collector
- Concurrent Mark-Sweep (CMS) Collector
Gerade für Serversysteme wird nicht der CMS Collector von der JVM als Standardcollector gewählt. Der CMS wäre aber die bessere Wahl, wenn man auf kurze Programmunterbrechungen während des GC legt, aber dafür etwas mehr CPU und Speicherverbrauch in kauf nimmt.
Weitere Vor- und Nachteile sowie Einstellungsmöglichkeiten am GC sind in Memory Management in the Java HotSpot Virtual Machine anschaulich beschrieben (dort kann man auch nachlesen, weshalb es 2 Survivor Spaces gibt).
Für die Untersuchung der aktuellen Heapbelegung eignet sich jconsole, was bei Sun Java standardmäßig mitgeliefert wird.
PS: Ab Java 7 wird ein weiterer GC (G1) eingeführt. Experimentierfreudige können G1 auch schon in Java 6 aktivieren.

