Behandlung von NoClassDefFoundError für JAXBException in Java 9

1. Einleitung

Für alle, die versucht haben, ein Upgrade auf Java 9 durchzuführen, ist beim Kompilieren von Code, der zuvor in früheren Java-Versionen funktioniert hat, wahrscheinlich eine Art NoClassDefFoundError aufgetreten .

In diesem Artikel werden wir uns eine häufig fehlende Klasse, JAXBException , und verschiedene Möglichkeiten zur Lösung ansehen . Die hier bereitgestellten Lösungen gelten im Allgemeinen für alle Klassen, die beim Upgrade auf Java 9 möglicherweise fehlen.

2. Warum kann Java 9 JAXBException nicht finden ?

Eine der am meisten diskutierten Funktionen von Java 9 ist das Modulsystem. Das Ziel des Java 9-Modulsystems besteht darin, die Kern-JVM-Klassen und verwandte Projekte in eigenständige Module zu unterteilen . Auf diese Weise können wir Anwendungen mit geringerem Platzbedarf erstellen, indem nur die zum Ausführen erforderlichen Mindestklassen berücksichtigt werden.

Der Nachteil ist, dass viele Klassen standardmäßig nicht mehr im Klassenpfad verfügbar sind. In diesem Fall befindet sich die Klasse JAXBException in einem der neuen Jakarta EE-Module mit dem Namen java.xml.bind . Da dieses Modul für die Java-Kernlaufzeit nicht erforderlich ist, ist es standardmäßig nicht im Klassenpfad verfügbar.

Der Versuch, eine Anwendung auszuführen , die JAXBException verwendet, führt zu:

NoClassDefFoundError: javax/xml/bind/JAXBException

Um dies zu umgehen, müssen wir das Modul java.xml.bind einschließen . Wie wir weiter unten sehen werden, gibt es mehrere Möglichkeiten, dies zu erreichen.

3. Kurzfristige Lösung

Der schnellste Weg , um sicher die JAXB API - Klassen zur Verfügung zu stellen sind für eine Anwendung ist hinzuzufügen Verwendung die -add-Module Befehlszeilenargument :

--add-modules java.xml.bind

Dies ist jedoch aus mehreren Gründen möglicherweise keine gute Lösung.

Erstens ist das Argument –add-modules auch in Java 9 neu. Für Anwendungen, die auf mehreren Java-Versionen ausgeführt werden müssen, stellt dies einige Herausforderungen dar. Wir müssten mehrere Sätze von Build-Dateien verwalten, einen für jede Java-Version, auf der die Anwendung ausgeführt wird.

Um dies zu umgehen, können wir auch das Befehlszeilenargument -XX: + IgnoreUnrecognizedVMOptions für ältere Java-Compiler verwenden.

Dies bedeutet jedoch, dass Tippfehler oder falsch geschriebene Argumente nicht auf uns aufmerksam gemacht werden. Wenn wir beispielsweise versuchen, eine minimale oder maximale Heap-Größe festzulegen und den Argumentnamen falsch einzugeben, wird keine Warnung angezeigt. Unsere Anwendung wird weiterhin gestartet, jedoch mit einer anderen Konfiguration als erwartet ausgeführt.

Zweitens wird die Option –add-modules in einer zukünftigen Java-Version nicht mehr unterstützt. Dies bedeutet, dass wir irgendwann nach dem Upgrade auf eine neue Java-Version das gleiche Problem haben, ein unbekanntes Befehlszeilenargument zu verwenden, und das Problem erneut beheben müssen.

4. Langfristige Lösung

Es gibt einen besseren Ansatz, der für verschiedene Java-Versionen funktioniert und nicht mit zukünftigen Versionen bricht.

Die Lösung besteht darin , ein Abhängigkeitsmanagement-Tool wie Maven zu verwenden . Mit diesem Ansatz würden wir die JAXB-API-Bibliothek wie jede andere Bibliothek als Abhängigkeit hinzufügen:

 javax.xml.bind jaxb-api 2.3.0 

Die obige Bibliothek enthält nur die JAXB-API-Klassen, einschließlich JAXBException . Je nach Anwendung müssen möglicherweise andere Module hinzugefügt werden.

Beachten Sie auch, dass sich die Namen der Maven-Artefakte möglicherweise vom Namen des Java 9-Moduls unterscheiden , wie dies bei der JAXB-API der Fall ist. Es kann auf Maven Central gefunden werden.

5. Schlussfolgerung

Das Java 9-Modulsystem bietet eine Reihe von Vorteilen, z. B. eine Verringerung der Anwendungsgröße und eine bessere Leistung.

Es bringt jedoch auch einige unbeabsichtigte Konsequenzen mit sich. Beim Upgrade auf Java 9 ist es wichtig zu verstehen, welche Module eine Anwendung wirklich benötigt, und Schritte zu unternehmen, um sicherzustellen, dass sie im Klassenpfad verfügbar sind.