Zum Inhalt springen

Ratgeber

Java-8-Upgrade: kritische Anwendung auf modernes Java heben

· 6 Min. Lesezeit

Aktualisieren Sie eine kritische Java-8-Anwendung in Etappen: Erfassen Sie jede Abhängigkeit, wechseln Sie zuerst auf Java 11, dann auf jedes spätere Release mit Langzeitsupport (LTS), und lassen Sie Tests und Lasttests entscheiden, wann jeder Schritt sicher ist. Die meiste Arbeit steckt in Bibliotheken, Build-Werkzeugen und Code, der JDK-Interna berührt, nicht in Ihrer Geschäftslogik.

Wer auf Java 8 bleibt, hat jedes Jahr weniger Optionen

Eine Java-8-Anwendung kann jahrelang weiterlaufen, und genau das ist die Falle. Sicherheitsupdates hängen zunehmend von einem kostenpflichtigen Supportvertrag oder einer Distribution ab, die sie noch zurückportiert, und wichtige Bibliotheken haben sich weiterentwickelt. Spring Boot 3 etwa setzt mindestens Java 17 voraus: Wer auf Java 8 bleibt, friert also auch seine Framework-Versionen ein.

Neuere JVMs führen denselben Code außerdem besser aus. G1 ist seit Java 9 der Standard-Garbage-Collector, Collectors mit kurzen Pausen wie ZGC sind produktionsreif, und Compact Strings senken den Speicherbedarf bei textlastigen Workloads. Entwickler erwarten zudem moderne Sprachfunktionen wie Records, Text Blocks und Switch Expressions, was es schwerer macht, für eine Java-8-Codebasis Personal zu finden.

Beginnen Sie mit einem Inventar aller Abhängigkeiten der Anwendung

Das Upgrade des JDK selbst ist selten der schwierige Teil. Schwierig ist der lange Schwanz an Bibliotheken, Plugins und Agents, die für Java 8 geschrieben und nie aktualisiert wurden. Erstellen Sie eine vollständige Liste, bevor Sie etwas ändern, und notieren Sie die Version jedes Eintrags.

  • Anbieter und Version des JDK in jeder Umgebung, von den Laptops der Entwickler bis zur Produktion.
  • Direkte und transitive Abhängigkeiten, exportiert aus dem Maven-Abhängigkeitsbaum oder dem Gradle-Abhängigkeitsbericht.
  • Build-Plugins, Codegeneratoren und Annotation-Prozessoren wie Lombok.
  • Der Applikationsserver oder Servlet-Container, falls die Anwendung darin läuft.
  • Java-Agents für Monitoring, Profiling oder Sicherheit, die tief in die JVM eingreifen.
  • Code, der interne JDK-APIs nutzt, gefunden mit dem Tool jdeps und seiner Option jdk-internals.
  • JVM-Flags, Einstellungen des Garbage Collectors und alle Skripte, die die Ausgabe von java -version auswerten.

Gehen Sie die LTS-Releases Schritt für Schritt durch, statt zu springen

Wechseln Sie von Java 8 auf 11, dann auf 17, dann auf 21 oder 25. Jeder Schritt hat seine eigenen Entfernungen und Verhaltensänderungen, und ein einziger Sprung vermischt sie alle zu einem Fehler, den Sie nicht diagnostizieren können. Wenn Sie eine Schicht nach der anderen beheben, bleibt jeder Schritt klein genug, um ihn zu prüfen und zurückzurollen.

Aktualisieren Sie Bibliotheken nach Möglichkeit noch unter Java 8, denn viele aktuelle Versionen unterstützen alte und neue JDKs. Lassen Sie dann den bestehenden Build auf der neuen JVM laufen, bevor Sie das Kompilierungsziel ändern. So trennen Sie Laufzeitprobleme von Compilerproblemen, und das Compiler-Flag release hält das Bytecode-Ziel explizit.

Machen Sie die Testsuite zur Hürde für jeden Schritt

Tests sind Ihr einziges objektives Signal dafür, dass sich die aktualisierte Anwendung weiterhin gleich verhält. Sind kritische Pfade kaum abgedeckt, schreiben Sie zuerst Charakterisierungstests: Tests, die festhalten, was das System heute tut, einschließlich seiner merkwürdigen Grenzfälle, ohne zu beurteilen, ob dieses Verhalten richtig ist.

Ergänzen Sie Integrationstests, die gegen eine echte Datenbank und echte Message Broker laufen, denn viele Upgrade-Fehler zeigen sich erst an diesen Grenzen. Spielen Sie bei rechenintensiven Systemen dieselben Eingaben durch die alte und die neue Version und vergleichen Sie die Ausgaben Feld für Feld. Achten Sie auf Datumsangaben, Zahlen und Text: Java 9 nutzt standardmäßig die Locale-Daten von CLDR, und Java 18 hat UTF-8 zum Standardzeichensatz gemacht; beides kann Formatierung oder Parsing unbemerkt verändern.

Kennen Sie die Fallstricke, an denen Java-8-Code scheitert

Die meisten Brüche fallen in wenige bekannte Kategorien. Suchen Sie vor dem Upgrade nach jeder davon, statt sie in der Produktion zu entdecken.

  • Entfernte Java-EE- und CORBA-Module: Java 11 hat JAXB, JAX-WS, JavaBeans Activation und die Common Annotations aus dem JDK entfernt, sie müssen also als explizite Abhängigkeiten wieder hinzugefügt werden.
  • Starke Kapselung der JDK-Interna: Illegaler reflektiver Zugriff erzeugte ab Java 9 Warnungen, wird seit Java 16 standardmäßig verweigert und lässt sich seit Java 17 nicht mehr global wieder einschalten. Beheben Sie das durch ein Upgrade der Bibliothek; nutzen Sie add-opens nur als dokumentierte, vorübergehende Ausnahme.
  • Veraltete Bytecode-Werkzeuge: Ältere Versionen von Lombok, Mockito, Byte Buddy, ASM und Build-Plugins scheitern an neueren Class-File-Versionen.
  • Entfernte Funktionen: Die JavaScript-Engine Nashorn wurde in Java 15 entfernt, und der Security Manager wurde in Java 17 als veraltet markiert und in Java 24 dauerhaft deaktiviert.
  • Entfernte JVM-Flags: Der CMS-Garbage-Collector wurde in Java 14 entfernt, und eine JVM, die mit entfernten Optionen gestartet wird, kann den Start verweigern.

Weisen Sie die Performance unter realistischer Last nach, nicht auf einem Laptop

Ein neues JDK verändert Garbage Collector, JIT-Compiler und Speicherlayout, die Performance kann sich also in beide Richtungen bewegen. Führen Sie vor und nach jedem Schritt einen Lasttest durch, der das Traffic-Profil der Produktion nachbildet, auf derselben Hardware oder demselben Instanztyp. Vergleichen Sie Latenz-Perzentile, Durchsatz, Speicher und GC-Pausen, und lassen Sie den JIT warmlaufen, bevor Sie messen.

Unsere Entwickler haben über Sopra Steria die Migration einer kritischen Day-Trading-Anwendung für Gas von Java 8 auf 16 geleitet, für einen nationalen Gas-Handelsdesk. In diesem System mussten Kapazitäts- und Energieflussberechnungen unter hochfrequenter Last korrekt und schnell bleiben. Deshalb ging das Upgrade mit Optimierungsarbeit an diesen Berechnungen einher und wurde unter Last validiert, statt es einfach vorauszusetzen.

Führen Sie schrittweise ein und behalten Sie einen Weg zurück

Bringen Sie die aktualisierte Laufzeitumgebung zuerst auf eine Instanz oder einen kleinen Teil des Traffics und beobachten Sie Fehlerraten, Latenz und das Verhalten des Garbage Collectors im Vergleich zur Java-8-Basislinie. Halten Sie den vorherigen Build deploybar, bis die neue Version normale Geschäftszyklen durchlaufen hat, einschließlich Monatsende oder Spitzenzeiten.

Erst dann entfernen Sie die Java-8-Artefakte und beginnen, neue Sprachfunktionen zu nutzen. Wenn Sie Unterstützung bei der Planung oder Umsetzung eines solchen Upgrades möchten, stellt SDK Enterprises dafür interne Entwickler und geprüfte Spezialisten, unter einem Vertrag mit klarer Verantwortung.

Das Wichtigste in Kürze

  • Der Aufwand bei einem Java-8-Upgrade steckt vor allem in Abhängigkeiten, Build-Werkzeugen und der Nutzung von JDK-Interna, nicht in der Geschäftslogik.
  • Gehen Sie die LTS-Releases einzeln durch, damit jeder Fehler eine einzige, auffindbare Ursache hat.
  • Charakterisierungs- und Integrationstests sind die Hürde für jeden Schritt, besonders bei Datumsangaben, Zahlen und Textkodierung.
  • Validieren Sie die Performance unter produktionsnaher Last, denn Änderungen an Garbage Collection und JIT können die Ergebnisse in beide Richtungen verschieben.
  • Führen Sie zuerst auf einem kleinen Teil des Traffics ein und halten Sie den Java-8-Build deploybar, bis sich die neue Laufzeitumgebung bewährt hat.

FAQ

Kann man direkt von Java 8 auf Java 21 wechseln?

Das geht, aber Sie übernehmen alle Änderungen von Java 9 bis 21 auf einmal, was Fehler schwer nachvollziehbar macht. Der Weg über 11 und 17 kostet etwas mehr Build-Zeit und erspart bei einem kritischen System viel Fehlersuche.

Wie lange dauert ein Java-8-Upgrade?

Das hängt von der Zahl der Abhängigkeiten ab, davon, wie viele davon JDK-Interna nutzen, von der Testabdeckung und davon, wie viel Lasttests das System braucht. Ein Inventar und ein Probelauf auf der neuen JVM liefern Ihnen früh eine realistische Schätzung, bevor Sie sich auf einen Zeitplan festlegen.

Muss man Code neu schreiben, um neue Java-Funktionen zu nutzen?

Nein. Java bleibt für Code, der sich an standardisierte, nicht veraltete APIs hält, weitgehend abwärtskompatibel. Führen Sie Records, Text Blocks und andere Funktionen schrittweise ein, sobald die aktualisierte Laufzeitumgebung in der Produktion stabil läuft.

Sagen Sie uns, was Sie brauchen.

Etwas zu entwickeln, Personen zu finden oder eine Frage zu klären. In einem 30-minütigen Gespräch hören wir zu und sagen Ihnen ehrlich, wie wir helfen können und was es dafür braucht.

Termin buchen

30 Minuten, auf Französisch oder Englisch. Kostenlos.

Lieber schreiben? Schicken Sie uns stattdessen eine kurze Anfrage.