Gestione di NoClassDefFoundError per JAXBException in Java 9

1. Introduzione

Chiunque abbia provato ad aggiornare a Java 9, ha probabilmente sperimentato una sorta di NoClassDefFoundError durante la compilazione di codice che in precedenza funzionava nelle versioni precedenti di Java.

In questo articolo, esamineremo una classe mancante comune, JAXBException , e diversi modi in cui possiamo risolverla. Le soluzioni fornite qui sono generalmente applicabili a qualsiasi classe che potrebbe mancare durante l'aggiornamento a Java 9.

2. Perché Java 9 non riesce a trovare JAXBException ?

Una delle caratteristiche più discusse di Java 9 è il sistema di moduli. L'obiettivo del sistema di moduli Java 9 è di suddividere le classi JVM principali e i progetti correlati in moduli autonomi . Questo ci aiuta a creare applicazioni con footprint più piccoli includendo solo le classi minime richieste per l'esecuzione.

Lo svantaggio è che molte classi non sono più disponibili sul classpath per impostazione predefinita. In questo caso, la classe JAXBException può essere trovata in uno dei nuovi moduli EE di Jakarta denominato java.xml.bind . Poiché questo modulo non è richiesto dal runtime Java di base, non è disponibile per impostazione predefinita sul classpath.

Il tentativo di eseguire un'applicazione che utilizza JAXBException comporterà:

NoClassDefFoundError: javax/xml/bind/JAXBException

Per aggirare questo problema dobbiamo includere il modulo java.xml.bind . Come vedremo di seguito, ci sono diversi modi per farlo.

3. Soluzione a breve termine

Il modo più rapido per assicurarsi che le classi API JAXB siano disponibili per un'applicazione è aggiungere l' uso dell'argomento della riga di comando –add-modules :

--add-modules java.xml.bind

Tuttavia, questa potrebbe non essere una buona soluzione per un paio di motivi.

Innanzitutto, anche l' argomento –add-modules è nuovo in Java 9. Per le applicazioni che devono essere eseguite su più versioni di Java, questo presenta alcune sfide. Dovremmo mantenere più set di file di build, uno per ogni versione di Java su cui viene eseguita l'applicazione.

Per ovviare a questo problema potremmo anche utilizzare l' argomento della riga di comando -XX: + IgnoreUnrecognizedVMOptions per i compilatori Java precedenti.

Tuttavia, questo significa che qualsiasi errore di battitura o argomento con errori di ortografia non verrà portato alla nostra attenzione. Ad esempio, se proviamo a impostare una dimensione di heap minima o massima e digitiamo erroneamente il nome dell'argomento, non riceveremo un avviso. La nostra applicazione verrà comunque avviata, ma verrà eseguita con una configurazione diversa da quella prevista.

In secondo luogo, l' opzione –add-modules sarà deprecata in una futura versione di Java. Ciò significa che ad un certo punto dopo l'aggiornamento a una nuova versione di Java, dovremo affrontare lo stesso problema dell'utilizzo di un argomento della riga di comando sconosciuto e dovremo risolvere nuovamente il problema.

4. Soluzione a lungo termine

Esiste un approccio migliore che funzionerà su diverse versioni di Java e non si interromperà con le versioni future.

La soluzione è utilizzare uno strumento di gestione delle dipendenze come Maven . Con questo approccio aggiungeremmo la libreria API JAXB come dipendenza proprio come qualsiasi altra libreria:

 javax.xml.bind jaxb-api 2.3.0 

La libreria precedente contiene solo le classi API JAXB, che include JAXBException . A seconda dell'applicazione, potrebbe essere necessario includere altri moduli.

Inoltre, tieni presente che i nomi degli artefatti Maven potrebbero essere diversi dal nome del modulo Java 9 , come nel caso dell'API JAXB. Può essere trovato su Maven Central.

5. conclusione

Il sistema del modulo Java 9 offre una serie di vantaggi come la riduzione delle dimensioni dell'applicazione e migliori prestazioni.

Tuttavia, introduce anche alcune conseguenze indesiderate. Quando si aggiorna a Java 9 è importante capire quali moduli richiede veramente un'applicazione e adottare misure per assicurarsi che siano disponibili sul classpath.