← Zur Lab-Übersicht

JVM-Performance: vom Symptom zur belastbaren Diagnose

Dieses Lab behandelt JVM-Performance nicht als Sammlung magischer Flags. Ausgangspunkt ist ein Produktionssymptom: Die p95-Latenz steigt, der Prozess benötigt mehr Speicher und einzelne Instanzen werden neu gestartet. Aus einem korrelierten Snapshot entstehen überprüfbare Hypothesen, konkrete nächste Messungen und ein Vorher-/Nachher-Vergleich.

Lernziele

Der Diagnosepfad

  1. Symptom: Latenz, Durchsatz, Fehlerquote, Restarts und Zeitpunkt festhalten.
  2. Snapshot: Heap, Non-Heap, Threads, GC, Classloading, CPU und Container gemeinsam erfassen.
  3. Hypothese: Eine primäre Ursache benennen, aber Unsicherheit sichtbar lassen.
  4. Vertiefung: Mit JFR, Heap Dump, Thread Dumps, NMT oder Traces gezielt nachmessen.
  5. Änderung: Im Szenario wird unbegrenzte Retention durch einen begrenzten LRU-Cache ersetzt.
  6. Vergleich: Heap-Auslastung, Allokationsrate und p95-Latenz werden erneut bewertet.

Zentrale Klassen

KlasseVerantwortungLernpunkt
JvmDiagnosticSnapshotKorreliert Messwerte eines Zeitpunkts.Einzelmetriken ohne Zeitbezug führen zu falschen Schlüssen.
JvmIncidentClassifierErzeugt Diagnose, Evidenz und nächste Schritte.Heuristiken liefern eine Hypothese, keinen Beweis.
DiagnosticScenarioFactoryDefiniert reproduzierbare Vorher-/Nachher-Snapshots.Optimierung braucht vergleichbare Bedingungen.
GcLogParserLiest Lehrformat und Java Unified Logging.Parser und Diagnose bleiben getrennt testbar.
BenchmarkReportBerechnet Median und p95.Eine Einzelmessung ist kein Benchmark.
ThreadStateSamplerZählt Zustände und erkennt Deadlocks.Viele Threads bedeuten nicht automatisch hohe Parallelität.

Ausführen

mvn clean test
java -cp target/classes com.example.enterprise.run8a.Run8ATestRunner
java -cp target/classes com.example.enterprise.run8a.Run8ADemo

Messgrenzen

Die Schwellenwerte des Klassifikators sind bewusst lesbare Lehrwerte, keine universellen Produktionsgrenzen. Ein echtes System benötigt Baselines pro Workload, Zeitreihen und die Korrelation mit Deployments und fachlichem Traffic. System.nanoTime() eignet sich für lokale Instrumentierung, aber nicht allein für belastbare Microbenchmarks: JIT-Warm-up, Dead-Code-Elimination, CPU-Frequenz, GC und Ausreißer müssen kontrolliert werden. Dafür ist JMH vorgesehen.

Nächster Schritt: Öffne das JVM Incident Runbook. Variiere die Snapshots und ergänze für jede Diagnose mindestens eine Gegenhypothese. Die Tests zeigen, dass alle Zweige der Decision Table erreichbar sind.
⌂ Cockpit