Cómo resolver java.lang.NoClassDefFoundError: javax/xml/bind/JAXBException

Resuelto Andy Guibert asked hace 7 años • 46 respuestas

Tengo un código que utiliza clases API JAXB que se han proporcionado como parte del JDK en Java 6/7/8. Cuando ejecuto el mismo código con Java 9, en tiempo de ejecución recibo errores que indican que no se pueden encontrar las clases JAXB.

Las clases JAXB se han proporcionado como parte del JDK desde Java 6, entonces, ¿por qué Java 9 ya no puede encontrar estas clases?

Andy Guibert avatar Apr 24 '17 00:04 Andy Guibert
Aceptado

Las API JAXB se consideran API de Java EE y, por lo tanto, ya no están contenidas en la ruta de clase predeterminada en Java SE 9. En Java 11, se eliminan por completo del JDK.

Java 9 introduce los conceptos de módulos y, de forma predeterminada, el java.semódulo agregado está disponible en la ruta de clases (o más bien, en la ruta del módulo). Como su nombre lo indica, el java.semódulo agregado no incluye las API de Java EE que tradicionalmente se incluyen con Java 6/7/8.

Afortunadamente, estas API de Java EE que se proporcionaron en JDK 6/7/8 todavía están en el JDK, pero simplemente no están en el classpath de forma predeterminada. Las API de Java EE adicionales se proporcionan en los siguientes módulos:

java.activation
java.corba
java.transaction
java.xml.bind  << This one contains the JAXB APIs
java.xml.ws
java.xml.ws.annotation

Solución rápida y sucia: (solo JDK 9/10)

Para que las API JAXB estén disponibles en tiempo de ejecución, especifique la siguiente opción de línea de comandos:

--add-modules java.xml.bind

¡¡¡Pero todavía necesito que esto funcione con Java 8!!!

Si intenta especificar --add-modulescon un JDK anterior, explotará porque es una opción no reconocida. Sugiero una de dos opciones:

  1. Puede configurar cualquier opción exclusiva de Java 9+ utilizando la JDK_JAVA_OPTIONSvariable de entorno. El iniciador de Java 9+ lee automáticamente esta variable de entorno java.
  2. Puede agregar -XX:+IgnoreUnrecognizedVMOptionspara hacer que la JVM ignore silenciosamente las opciones no reconocidas, en lugar de explotar. ¡Pero cuidado! La JVM ya no validará ningún otro argumento de línea de comandos que utilice. Esta opción funciona con Oracle/OpenJDK así como con IBM JDK (a partir de JDK 8sr4).

Solución rápida alternativa: (solo JDK 9/10)

Tenga en cuenta que puede hacer que todos los módulos Java EE anteriores estén disponibles en tiempo de ejecución especificando la --add-modules java.se.eeopción. El java.se.eemódulo es un módulo agregado que incluye, java.se.eeademás de los módulos API de Java EE anteriores. Tenga en cuenta que esto no funciona en Java 11 porque java.se.eese eliminó en Java 11.


Solución adecuada a largo plazo: (JDK 9 y posteriores)

Todos los módulos de la API de Java EE enumerados anteriormente están marcados @Deprecated(forRemoval=true)porque su eliminación está programada en Java 11 . Por lo tanto, el --add-moduleenfoque ya no funcionará en Java 11 listo para usar.

Lo que deberá hacer en Java 11 y posteriores es incluir su propia copia de las API de Java EE en la ruta de clases o la ruta del módulo. Por ejemplo, puede agregar las API JAX-B como una dependencia de Maven como esta:

<!-- API, java.xml.bind module -->
<dependency>
    <groupId>jakarta.xml.bind</groupId>
    <artifactId>jakarta.xml.bind-api</artifactId>
    <version>2.3.2</version>
</dependency>

<!-- Runtime, com.sun.xml.bind module -->
<dependency>
    <groupId>org.glassfish.jaxb</groupId>
    <artifactId>jaxb-runtime</artifactId>
    <version>2.3.2</version>
</dependency>

Consulte la página de implementación de referencia de JAXB para obtener más detalles sobre JAXB.

Para obtener detalles completos sobre la modularidad de Java, consulte JEP 261: Sistema de módulos

En julio de 2022, la última versión de bind-api y jaxb-runtime es 4.0.0. Entonces también puedes usar

    <version>4.0.0</version>

...dentro de esas cláusulas de dependencia. Pero si lo hace, los nombres de los paquetes cambiarán de javax.xml.bind...a jakarta.xml.bind.... Deberá modificar su código fuente para utilizar estas versiones posteriores de los JAR.

Para desarrolladores de Gradle o Android Studio: (JDK 9 y posteriores)

Agregue las siguientes dependencias a su build.gradlearchivo:

dependencies {
    // JAX-B dependencies for JDK 9+
    implementation "jakarta.xml.bind:jakarta.xml.bind-api:2.3.2"
    implementation "org.glassfish.jaxb:jaxb-runtime:2.3.2"
}
Andy Guibert avatar Apr 23 '2017 17:04 Andy Guibert

En mi caso (frasco de grasa de arranque de primavera), simplemente agrego lo siguiente a pom.xml.

<dependency>
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
    <version>2.3.1</version>
</dependency>
jdev avatar Nov 21 '2017 12:11 jdev

Solución limpia para todos los JDK >= 9

Necesitas agregar dos dependencias a tu compilación.

  • el jaxb-api
  • una implementación de jaxb

Como implementación, elegí utilizar la implementación de referencia de glassfish para deshacerme de las antiguas clases/bibliotecas de com.sun. Como resultado, agregué en mi compilación maven

<dependency>
  <groupId>javax.xml.bind</groupId>
  <artifactId>jaxb-api</artifactId>
  <version>2.3.1</version>
</dependency>

<dependency>
  <groupId>org.glassfish.jaxb</groupId>
  <artifactId>jaxb-runtime</artifactId>
  <version>2.3.1</version>
</dependency>

Tenga en cuenta que a partir de la versión 2.3.1 ya no es necesario agregar javax.activation. (ver https://github.com/eclipse-ee4j/jaxb-ri/issues/1222 )

Sebastian Thees avatar Oct 18 '2018 10:10 Sebastian Thees