Optimierung der Leistung von Java-Anwendungen: praktische Methoden und Tipps

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Optimierung der Leistung von Java-Anwendungen: Von der Theorie zur Praxis



Java bleibt eine der beliebtesten Sprachen für die Entwicklung von Unternehmens- und hochlastigen Systemen. Allerdings kann selbst eine gut geschriebene Anwendung mit der Zeit langsamer werden, zu viel Speicher verbrauchen oder OutOfMemoryError-Fehler ausgeben. In diesem Artikel behandeln wir die wichtigsten Methoden zur Leistungsoptimierung von Java-Anwendungen, die Ihnen helfen, Ihren Code schneller und effizienter zu machen. Sie erfahren, wie Sie die JVM konfigurieren, die Speicherverwaltung optimieren, typische Fehler vermeiden und moderne Profiling-Tools einsetzen.



1. Profiling und Identifikation von Engpässen



Bevor Sie etwas optimieren, müssen Sie verstehen, was genau die Verlangsamung verursacht. Intuitive Vermutungen sind oft falsch – der Engpass könnte eine andere Methode sein, als die, die langsam erscheint. Daher ist der erste Schritt das Profiling. Verwenden Sie Tools wie VisualVM, JProfiler oder den integrierten Java Flight Recorder (JFR).



Beispiel für das Starten des Profilings über JFR von der Kommandozeile:



java -XX:StartFlightRecording=duration=60s,filename=recording.jfr \     -jar my-application.jar


Öffnen Sie die Datei nach der Aufzeichnung im JDK Mission Control und betrachten Sie:

  • CPU-Profil – welche Methoden die meiste Prozessorzeit verbrauchen.
  • Speicher – welche Objekte am häufigsten erstellt werden und den meisten Platz belegen.
  • Threads – ob es Blockaden oder lange Wartezeiten gibt.


Erst nach der Datenanalyse können Sie mit den Korrekturen beginnen. Ohne Profiling riskieren Sie, etwas zu optimieren, das kein Problem darstellt.



2. Konfiguration der JVM und des Garbage Collectors



Die richtige Konfiguration der Java Virtual Machine (JVM) kann die Leistung um ein Vielfaches steigern. Die wichtigsten Parameter, die Sie anpassen sollten:



  • Heap-Größe – Parameter -Xms (Startgröße) und -Xmx (maximale Größe). Geben Sie keine zu große Startgröße an, wenn die Anwendung nicht so viel Speicher benötigt.
  • Auswahl des Garbage Collectors (GC) – Moderne Anwendungen profitieren oft von G1GC (Standard seit Java 9) oder ZGC (für große Heaps und niedrige Latenzen).


Beispiel für den Start mit optimierten Einstellungen:



java -Xms2g -Xmx4g \     -XX:+UseG1GC \     -XX:MaxGCPauseMillis=200 \     -XX:+ParallelRefProcEnabled \     -jar my-app.jar


Beachten Sie das Flag -XX:MaxGCPauseMillis. Es legt die Ziel-Pausenzeit des Garbage Collectors fest. Wenn Ihre Anwendung empfindlich auf Verzögerungen reagiert, versuchen Sie, 100-200 ms einzustellen. Ein zu niedriger Wert kann jedoch häufige Sammlungen verursachen und den Durchsatz verringern.



Es ist auch nützlich, das GC-Logging zu aktivieren, um zu sehen, wie der Collector arbeitet:



-Xlog:gc*:file=gc.log:time,uptime,level,tags


3. Code-Optimierung: Effiziente Datenstrukturen und Algorithmen



Selbst die beste JVM-Konfiguration hilft nicht, wenn der Code suboptimal geschrieben ist. Hier sind einige konkrete Empfehlungen mit Beispielen:



3.1. Verwenden Sie die richtigen Collections

Verwenden Sie kein ArrayList, wenn Sie häufig Elemente am Anfang einer Liste einfügen müssen – das ist O(n). Nehmen Sie stattdessen LinkedList oder ArrayDeque. Für die Suche nach Schlüsseln verwenden Sie HashMap oder TreeMap, nicht Listen.



Schlechtes Beispiel:

List<String> names = new ArrayList<>();for (int i = 0; i < 100000; i++) {    names.add(0, "Name" + i); // O(n) pro Einfügung}


Gutes Beispiel:

List<String> names = new LinkedList<>();for (int i = 0; i < 100000; i++) {    name                

Blogs

Buchempfehlungen