1. JMX (Java Management Extensions): das Herz des JVM-Monitorings
Monitoring ist wie eine regelmäßige Vorsorgeuntersuchung für Ihre Anwendung. Wenn sich Logging mit einem Tagebuch vergleichen lässt, in das alles eingetragen wird, was bereits passiert ist, dann ist Monitoring ein Satz von Instrumenten, die den aktuellen Zustand des Systems anzeigen: Temperatur, Puls, Blutdruck, Blutzuckerspiegel und andere lebenswichtige Kennzahlen der JVM.
Es hilft zu verstehen, wie viel Speicher tatsächlich genutzt wird und ob er ausläuft, wie viele Threads laufen und in welchem Zustand sie sind – warten, werden ausgeführt oder sind blockiert. Man kann sehen, wie oft der Garbage Collector anspringt, wie stark die CPU ausgelastet ist, und rechtzeitig Warnzeichen wie plötzliche Anstiege des Speichers oder der Thread-Anzahl erkennen.
Kurz gesagt: Logging erzählt, was bereits passiert ist, während Monitoring zeigt, was gerade jetzt passiert.
JMX-Grundlagen: was es ist und wozu es dient
JMX ist eine Java-Technologie, die es ermöglicht, das Innenleben Ihrer Anwendung zu beobachten und sogar ein wenig zu steuern. Sie funktioniert über spezielle Objekte – MBean (Management Bean). Man kann sagen, das sind „Sensoren“ und „Schalter“ innerhalb der JVM: Die einen zeigen den Systemzustand, die anderen erlauben, etwas nachzujustieren.
Mit JMX können Sie erfahren, wie viel Speicher der JVM gerade zugeordnet ist, wie viele Threads aktiv sind, wie viel Zeit die Müllabfuhr benötigt und vieles mehr – ohne in den Code eingreifen oder die Anwendung neu starten zu müssen.
Wie es aufgebaut ist
In der JVM gibt es „out of the box“ bereits zahlreiche MBeans, die Informationen liefern über:
- Speicher (heap, non-heap);
- Garbage Collector (GC);
- Threads;
- Klassen (wie viele geladen/entladen sind);
- und sogar über die JVM selbst (Version, Startparameter).
JMX ist wie das Armaturenbrett im Auto. Sie sehen Geschwindigkeit, Drehzahl, Motortemperatur – und all das ist über standardisierte Sensoren (MBeans) verfügbar.
Wie greift man auf JMX zu
Der einfachste Weg ist die Nutzung des Standardwerkzeugs JConsole, das zum JDK gehört.
JConsole starten
- Öffnen Sie das Terminal/die Eingabeaufforderung.
- Führen Sie den Befehl aus:
jconsole - Wählen Sie den Java-Prozess aus, den Sie überwachen möchten (zum Beispiel Ihre Anwendung).
JConsole verbindet sich über JMX mit der JVM und zeigt Diagramme und Tabellen: Speichernutzung, Anzahl der Threads, Aktivität des Garbage Collectors usw.
Beispiel: Speicher und Threads ansehen
Öffnen Sie in JConsole die Reiter „Memory“ und „Threads“. Sie sehen, wie sich das Volumen des verwendeten Speichers ändert, wie viele Threads gerade leben, welche aktiv sind und welche warten.
Eigene MBeans
Sie können eigene MBeans zur Überwachung Ihrer spezifischen Metriken erstellen (z. B. Anzahl verarbeiteter Bestellungen). Das ist aber eher ein Thema für Fortgeschrittene: Die Standard-MBeans liefern bereits sehr viele Informationen.
2. VisualVM – visuelles Monitoring und Profiling
Wenn JConsole das „Armaturenbrett“ ist, dann ist VisualVM ein ganzes Diagnostikzentrum mit Röntgen, MRT und Blutuntersuchung. Es ermöglicht nicht nur Monitoring, sondern auch das Profiling der Anwendung, das Anfertigen von heap dumps, die Analyse von Lecks und die Sichtbarkeit, welche Methoden am meisten Zeit benötigen.
Installation und Start von VisualVM
- VisualVM ist in der JDK-Distribution enthalten (meist als jvisualvm), die neueste Version kann man auf visualvm.github.io herunterladen.
- Starten mit:
jvisualvm - Nach dem Start sehen Sie die Liste aller Java-Prozesse, die auf Ihrem Rechner laufen.
Verbindung mit einem Prozess
- Suchen Sie Ihren Prozess (z. B. Main oder MyApp) in der Liste.
- Doppelklicken Sie darauf – ein Tab mit Prozessinformationen öffnet sich.
- Fertig! Jetzt sehen Sie:
- CPU- und Speichernutzung in Echtzeit.
- Die Anzahl der Threads und ihren Zustand.
- Die Liste der geladenen Klassen.
- Die Möglichkeit, heap dump und thread dump zu erstellen.
Zentrale Funktionen von VisualVM
Mit VisualVM lässt sich verfolgen, wie der Speicher genutzt wird – sowohl heap als auch non-heap. Im Diagramm sieht man, ob der Verbrauch steigt oder sich stabilisiert. Um die Arbeit des Garbage Collectors zu prüfen, klicken Sie auf die Schaltfläche „Perform GC“ – die JVM versucht dann sofort, Speicher zu bereinigen. Sie können einen heap dump (Speicherabbild) erstellen und zur Lecksuche analysieren.
Das Tool zeigt auch den Zustand der Threads: wie viele gestartet sind, welche arbeiten, warten oder blockiert sind. Wenn ein deadlock auftritt, hilft VisualVM, ihn zu erkennen und die gegenseitigen Blockaden anzuzeigen.
Für tiefgehende Analysen gibt es Profiling: Sie sehen „heiße“ Methoden, die am meisten CPU-Zeit oder Speicher verbrauchen. Das ist nützlich, um unerwartete Performanceeinbrüche zu diagnostizieren.
Beispiel: Wir überwachen eine Mini-Anwendung
public class MemoryLeakDemo {
public static void main(String[] args) throws InterruptedException {
List<byte[]> memoryConsumers = new ArrayList<>();
for (int i = 0; i < 1000; i++) {
memoryConsumers.add(new byte[1024 * 1024]); // 1 MB
Thread.sleep(100); // Kurz warten, damit die Kurve glatter ist
}
System.out.println("Fertig! Vergessen Sie nicht, in VisualVM nachzuschauen :)");
Thread.sleep(60000); // Anwendung für die Analyse offen halten
}
}
Jetzt:
- Starten Sie das Programm.
- Öffnen Sie VisualVM und verbinden Sie sich mit dem Prozess.
- Sehen Sie, wie die Speichernutzung wächst.
- Erstellen Sie einen heap dump und finden Sie die speicherbelegenden Arrays.
3. Java Flight Recorder (JFR): die „Black Box“ für die JVM
Was ist JFR
Java Flight Recorder ist ein in die JVM integriertes Werkzeug zum Erfassen detaillierter Ereignisse über die Arbeit der Anwendung. Es ist die „Black Box“: JFR zeichnet auf, was in der JVM geschieht, um später Engpässe oder Ursachen von Vorfällen zu finden.
JFR erfasst:
- Ereignisse des GC;
- Informationen zu Threads;
- Aufrufhäufigkeit von Methoden und Zeitprofile;
- Pausen und Latenzen;
- Ausnahmen und Fehler.
Wie JFR aktiviert wird
Seit Java 11+ ist JFR direkt im OpenJDK enthalten.
Start mit JFR
java -XX:StartFlightRecording=filename=recording.jfr,duration=60s,settings=profile -jar MyApp.jar
- filename=recording.jfr — wohin die Aufzeichnung gespeichert wird.
- duration=60s — wie lange aufgezeichnet wird.
- settings=profile — Detailgrad (default, profile, continuous).
Ergebnisse ansehen
Zur Auswertung der .jfr-Datei verwendet man JDK Mission Control (JMC):
- JMC herunterladen: jdk.java.net/jmc
- Datei recording.jfr öffnen.
- Diagramme, „heiße“ Methoden, GC-Pausen und Thread-Aktivität untersuchen.
Beispiel: die „Black Box“ aufzeichnen
- Starten Sie die Anwendung mit JFR (siehe Kommando oben).
- Öffnen Sie JDK Mission Control und laden Sie die Aufzeichnungsdatei.
- Bewerten Sie Hotspots bei CPU/Speicher, die Häufigkeit der Garbage-Collection und die Anzahl aktiver Threads.
4. Praxis: Anwendung überwachen
import java.util.ArrayList;
import java.util.List;
public class MonitoringExample {
public static void main(String[] args) throws InterruptedException {
List<byte[]> memory = new ArrayList<>();
for (int i = 0; i < 50; i++) {
memory.add(new byte[2 * 1024 * 1024]); // 2 MB
Thread.sleep(500);
}
// Thread starten
new Thread(() -> {
while (true) {
try {
Thread.sleep(1000);
System.out.println("Der Hintergrund-Thread läuft...");
} catch (InterruptedException e) {
break;
}
}
}).start();
Thread.sleep(20000); // Anwendung für das Monitoring offen halten
}
}
Vorgehen:
- Starten Sie das Programm.
- Öffnen Sie VisualVM, suchen Sie den Prozess und betrachten Sie Speicherkurven und Threads.
- Versuchen Sie, einen heap dump und einen thread dump zu erstellen.
- Für Fortgeschrittene: Mit JFR starten und die Ergebnisse in JMC ansehen.
5. Nützliche Details
Vergleichstabelle der Monitoring-Werkzeuge
| Werkzeug | Wofür geeignet | Wie starten | Besonderheiten |
|---|---|---|---|
| JConsole (JMX) | Grundlegende JVM-Metriken, Threads, GC | |
Einfach, im JDK enthalten |
| VisualVM | Monitoring, Profiling, heap dump | |
Diagramme, Speicheranalyse, CPU |
| Java Flight Recorder | Tiefgehende Analyse von JVM-Ereignissen | |
Analyse in JMC, „Black Box“ |
| JDK Mission Control | Anzeige von JFR-Dateien | eigenständiges Programm | Detaillierte Analysen, Berichte |
Empfehlungen
- Überwachen Sie nicht nur in der Produktion, sondern schon in der Testphase. So fangen Sie Speicherecks und „hängende“ Threads früher ab.
- Heap dump – tut nicht weh! Erstellen Sie bei Verdacht auf ein Leak ein Speicherabbild und analysieren Sie es in VisualVM.
- Scheuen Sie sich nicht, mit JFR zu experimentieren. Auch wenn nicht sofort alles klar ist: Ereignisse und Diagramme helfen, Engpässe zu finden.
- JMX kann auch programmatisch genutzt werden. Zum Beispiel, um Metriken an Prometheus/Grafana zu senden.
- Profiling ist nichts für den Dauerbetrieb. Aktivieren Sie Profiler gezielt, sonst kann die Anwendung langsamer werden.
6. Typische Fehler beim JVM-Monitoring
Fehler Nr. 1: Gar kein Monitoring. Viele Einsteiger denken, wenn die Anwendung „läuft“, ist alles gut. In der Praxis zeigen sich Speicher- und Thread-Probleme oft unter Last oder erst nach einiger Zeit. Scheuen Sie sich nicht, VisualVM/JConsole zumindest gelegentlich zu öffnen.
Fehler Nr. 2: Heap dumps in riesigen Anwendungen ohne Vorbereitung erstellen. Ein heap dump einer großen Anwendung kann Gigabytes groß sein und den Prozess für einige Sekunden „einfrieren“. Machen Sie das in einer Testumgebung oder zu „ruhigen“ Zeiten, wenn es um Produktion geht.
Fehler Nr. 3: GC- und Thread-Metriken ignorieren. Ständig hoher Zeitanteil für den GC ist ein Alarmsignal! Und wenn die Thread-Anzahl stetig wächst – suchen Sie nach einem Thread-Leak.
Fehler Nr. 4: Monitoring-Ergebnisse nicht analysieren. Nur VisualVM zu öffnen, reicht nicht. Schauen Sie, welche Objekte Speicher belegen, welche Methoden CPU „fressen“, und warum deadlocks auftreten. Untersuchen Sie Stacktraces und Ursachen.
Fehler Nr. 5: Profiler in der Produktion ohne Verständnis einsetzen. Profiling kann die Anwendung deutlich verlangsamen. Aktivieren Sie es nur zur Diagnose, nicht „permanent“.
GO TO FULL VERSION