Gestion de NoClassDefFoundError pour JAXBException dans Java 9

1. Introduction

Pour tous ceux qui ont essayé de mettre à niveau vers Java 9, ils ont probablement rencontré une sorte de NoClassDefFoundError lors de la compilation de code qui fonctionnait auparavant dans les versions antérieures de Java.

Dans cet article, nous examinerons une classe manquante commune, JAXBException , et différentes façons de la résoudre. Les solutions fournies ici sont généralement applicables à toute classe qui peut manquer lors de la mise à niveau vers Java 9.

2. Pourquoi Java 9 ne trouve- t-il pas JAXBException ?

L'une des fonctionnalités les plus discutées de Java 9 est le système de modules. Le but du système de modules Java 9 est de séparer les classes JVM principales et les projets associés en modules autonomes . Cela nous aide à créer des applications avec des empreintes plus petites en incluant uniquement les classes minimales requises pour s'exécuter.

L'inconvénient est que de nombreuses classes ne sont plus disponibles par défaut sur le chemin des classes. Dans ce cas, la classe JAXBException se trouve dans l'un des nouveaux modules Jakarta EE nommé java.xml.bind . Comme ce module n'est pas requis par le runtime Java principal, il n'est pas disponible par défaut sur le chemin de classe.

Essayer d'exécuter une application qui utilise JAXBException entraînera:

NoClassDefFoundError: javax/xml/bind/JAXBException

Pour contourner ce problème, nous devons inclure le module java.xml.bind . Comme nous le verrons ci-dessous, il existe plusieurs façons d'accomplir cela.

3. Solution à court terme

Le moyen le plus rapide de s'assurer que les classes d'API JAXB sont disponibles pour une application consiste à utiliser l' argument de ligne de commande –add-modules :

--add-modules java.xml.bind

Cependant, cela pourrait ne pas être une bonne solution pour plusieurs raisons.

Tout d'abord, l' argument –add-modules est également nouveau dans Java 9. Pour les applications qui doivent s'exécuter sur plusieurs versions de Java, cela présente certains défis. Nous devrons gérer plusieurs ensembles de fichiers de construction, un pour chaque version Java sur laquelle l'application s'exécute.

Pour contourner ce problème, nous pourrions également utiliser l' argument de ligne de commande -XX: + IgnoreUnrecognizedVMOptions pour les anciens compilateurs Java.

Cependant, cela signifie que toute faute de frappe ou argument mal orthographié ne sera pas porté à notre attention. Par exemple, si nous essayons de définir une taille de tas minimale ou maximale et de saisir mal le nom de l'argument, nous n'obtiendrons pas d'avertissement. Notre application démarrera toujours, mais elle fonctionnera avec une configuration différente de celle prévue.

Deuxièmement, l' option –add-modules sera obsolète dans une future version de Java. Cela signifie qu'à un moment donné, après la mise à niveau vers une nouvelle version de Java, nous serons confrontés au même problème d'utilisation d'un argument de ligne de commande inconnu et devrons à nouveau résoudre le problème.

4. Solution à long terme

Il existe une meilleure approche qui fonctionnera sur différentes versions de Java et qui ne rompra pas avec les versions futures.

La solution consiste à utiliser un outil de gestion des dépendances tel que Maven . Avec cette approche, nous ajouterions la bibliothèque d'API JAXB en tant que dépendance, comme toute autre bibliothèque:

 javax.xml.bind jaxb-api 2.3.0 

La bibliothèque ci-dessus contient uniquement les classes d'API JAXB, qui incluent JAXBException . Selon l'application, nous pouvons avoir besoin d'inclure d'autres modules.

Gardez également à l'esprit que les noms d'artefacts Maven peuvent être différents du nom du module Java 9 , comme c'est le cas pour l'API JAXB. Il peut être trouvé sur Maven Central.

5. Conclusion

Le système de modules Java 9 offre un certain nombre d'avantages tels que la réduction de la taille de l'application et de meilleures performances.

Cependant, cela introduit également des conséquences imprévues. Lors de la mise à niveau vers Java 9, il est important de comprendre quels modules une application a vraiment besoin et de prendre des mesures pour s'assurer qu'ils sont disponibles sur le chemin de classe.