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

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

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

Las API de 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, por defecto, el módulo agregado java.se está disponible en la ruta de la clase (o más bien, la ruta del módulo). Como su nombre lo indica, el módulo agregado de java.se no incluye las API de Java EE que tradicionalmente se han incluido 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 la ruta de clase de forma predeterminada. Las API 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 de 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 intentas especificar --add-modules con un JDK antiguo, explotará porque es una opción no reconocida. Sugiero una de dos opciones:

  1. Puede aplicar condicionalmente el argumento en una secuencia de comandos de inicio (si tiene una) inspeccionando la versión de JDK inspeccionando $JAVA_HOME/release para la propiedad JAVA_VERSION .
  2. Puede agregar -XX:+IgnoreUnrecognizedVMOptions no reconocidas para 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 comando 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 anteriores de Java EE estén disponibles en tiempo de ejecución especificando la --add-modules java.se.ee El módulo java.se.ee es un módulo agregado que incluye java.se.ee así como también los módulos anteriores de la API de Java EE.


Solución adecuada a largo plazo: (Todas las versiones JDK)

Los módulos API de Java EE enumerados anteriormente están todos marcados como @Deprecated(forRemoval=true) , ya que están progtwigdos para su eliminación en Java 11 . Entonces el enfoque --add-module ya no funcionará en Java 11 de --add-module .

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

     javax.xml.bind jaxb-api 2.2.11   com.sun.xml.bind jaxb-core 2.2.11   com.sun.xml.bind jaxb-impl 2.2.11   javax.activation activation 1.1.1  

Para obtener más información sobre la modularidad de Java, consulte JEP 261: Sistema de módulos

En mi caso (flask de grasa de arranque de spring) simplemente agrego lo siguiente a pom.xml.

  javax.xml.bind jaxb-api 2.3.0  

Ninguna de estas soluciones funcionó bien para mí en el reciente JDK 9.0.1.

Descubrí que esta lista de dependencias es suficiente para un correcto funcionamiento, por lo que no es necesario especificar explícitamente --add-module (aunque está especificado dentro de las dependencias de este pom). Lo único que necesita es especificar esta lista de dependencias:

   javax.xml.bind jaxb-api 2.3.0   com.sun.xml.bind jaxb-impl 2.3.0   org.glassfish.jaxb jaxb-runtime 2.3.0   javax.activation activation 1.1.1   

Esto funcionó para mí:

  javax.xml.bind jaxb-api 2.3.0   org.eclipse.persistence eclipselink 2.7.0  

Como una dependencia para mi aplicación Java 8, que produce un * .jar que puede ser ejecutado por JRE 8 o JRE 9 sin argumentos adicionales.

Además, esto debe ejecutarse en algún lugar antes de que se use JAXB API:

 System.setProperty("javax.xml.bind.JAXBContextFactory", "org.eclipse.persistence.jaxb.JAXBContextFactory"); 

Funciona muy bien hasta ahora, como una solución. Aunque no parece una solución perfecta …

En el momento de la comstackción, así como del tiempo de ejecución, agregue el --add-modules java.xml.bind

 javac --add-modules java.xml.bind  java --add-modules java.xml.bind  

Una buena introducción a los módulos JDK 9 también se puede encontrar en: https://www.youtube.com/watch?v=KZfbRuvv5qc

Para resolver esto, he importado algunos archivos JAR en mi proyecto:

  • javax.activation-1.2.0.jar

http://search.maven.org/remotecontent?filepath=com/sun/activation/javax.activation/1.2.0/javax.activation-1.2.0.jar

  • jaxb-api-2.3.0.jar

http://search.maven.org/remotecontent?filepath=javax/xml/bind/jaxb-api/2.3.0/jaxb-api-2.3.0.jar

  • jaxb-core-2.3.0.jar

http://search.maven.org/remotecontent?filepath=com/sun/xml/bind/jaxb-core/2.3.0/jaxb-core-2.3.0.jar

  • jaxb-impl-2.3.0.jar

http://search.maven.org/remotecontent?filepath=com/sun/xml/bind/jaxb-impl/2.3.0/jaxb-impl-2.3.0.jar

  1. Descargue los archivos anteriores y cópielos en la carpeta libs del proyecto
  2. Agregue los archivos JAR importados en Java Build Path

Para Java Web Start Execution podemos usar la sugerencia de Andy Guibert así:

  

Tenga en cuenta el extra “=” en el –add-modules. Consulte este ticket de OpenJDK o la última nota en “Descripción de las advertencias de acceso en tiempo de ejecución” de la plataforma Java Platform, edición estándar de Oracle JDK 9 Guía de migración .

Esto funcionó para mí. Agregar solo jaxb-api no fue suficiente.

   javax.xml.bind jaxb-api ${jaxb-api.version}   com.sun.xml.bind jaxb-impl ${jaxb-api.version}   com.sun.xml.bind jaxb-core ${jaxb-api.version}  

Puede usar la opción de JVM ” –add-modules = java.xml.bind ” para agregar el módulo de enlace xml al entorno de tiempo de ejecución de JVM.

Ejemplo: “java –add-modules = java.xml.bind XmlTestClass”

Vaya a Build.gradle y agregue las dependencias a continuación para Java 9 o Java 10.

 sourceCompatibility = 10 // You can also decrease your souce compatibility to 1.8 //java 9+ does not have Jax B Dependents compile group: 'javax.xml.bind', name: 'jaxb-api', version: '2.3.0' compile group: 'com.sun.xml.bind', name: 'jaxb-core', version: '2.3.0' compile group: 'com.sun.xml.bind', name: 'jaxb-impl', version: '2.3.0' compile group: 'javax.activation', name: 'activation', version: '1.1.1' 

Siguiente ¿Qué artefactos debería usar para JAXB RI en mi proyecto Maven? En Maven, puedes usar un perfil como:

  java-9  9    org.glassfish.jaxb jaxb-runtime 2.3.0   javax.activation activation 1.1.1    

Árbol de dependencia muestra:

 [INFO] +- org.glassfish.jaxb:jaxb-runtime:jar:2.3.0:compile [INFO] | +- org.glassfish.jaxb:jaxb-core:jar:2.3.0:compile [INFO] | | +- javax.xml.bind:jaxb-api:jar:2.3.0:compile [INFO] | | +- org.glassfish.jaxb:txw2:jar:2.3.0:compile [INFO] | | \- com.sun.istack:istack-commons-runtime:jar:3.0.5:compile [INFO] | +- org.jvnet.staxex:stax-ex:jar:1.7.8:compile [INFO] | \- com.sun.xml.fastinfoset:FastInfoset:jar:1.2.13:compile [INFO] \- javax.activation:activation:jar:1.1.1:compile 

Para usar esto en Eclipse, digamos Oxygen.3a Release (4.7.3a) o posterior, Ctrl-Alt-P, o haga clic derecho en el proyecto, Maven, luego seleccione el perfil.

No es una respuesta, sino una adición: obtuve porque ejecutar groovysh (Groovy 2.4.13) si JAVA_HOME apunta a una instalación de Java 9 ( java version "9.0.1" para ser precisos) falla abysmally:

 java.lang.reflect.InvocationTargetException at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:564) at org.codehaus.groovy.tools.GroovyStarter.rootLoader(GroovyStarter.java:107) at org.codehaus.groovy.tools.GroovyStarter.main(GroovyStarter.java:129) Caused by: java.lang.NoClassDefFoundError: Unable to load class groovy.xml.jaxb.JaxbGroovyMethods due to missing dependency javax/xml/bind/JAXBContext at org.codehaus.groovy.vmplugin.v5.Java5.configureClassNode(Java5.java:400) at org.codehaus.groovy.ast.ClassNode.lazyClassInit(ClassNode.java:277) at org.codehaus.groovy.ast.ClassNode.getMethods(ClassNode.java:397) ... .. . .. ... at org.codehaus.groovy.tools.shell.Groovysh.(Groovysh.groovy:135) at org.codehaus.groovy.vmplugin.v7.IndyInterface.selectMethod(IndyInterface.java:232) at org.codehaus.groovy.tools.shell.Main.(Main.groovy:66) at org.codehaus.groovy.vmplugin.v7.IndyInterface.selectMethod(IndyInterface.java:232) at org.codehaus.groovy.tools.shell.Main.main(Main.groovy:163) ... 6 more 

La solución fue:

  • Vaya al Proyecto JAXB en github.io ( “JAXB está licenciado bajo una licencia dual – CDDL 1.1 y GPL 2.0 con excepción de ruta de clase” )

  • Descargar jaxb-ri-2.3.0.zip

  • Descomprime cada vez que coloques tus archivos de infraestructura de Java (en mi caso, /usr/local/java/jaxb-ri/ ). Puede existir otra solución (tal vez a través de SDKMAN, no sé)

  • Asegúrese de que los archivos jar en el subdirectorio lib estén en CLASSPATH . Lo hago a través de un script iniciado en el inicio de bash, llamado /etc/profile.d/java.sh , donde agregué (entre muchas otras líneas) el siguiente ciclo:

Embalado en una función …

 function extend_qzminynshg { local BASE="/usr/local/java" for LIB in jaxb-api.jar jaxb-core.jar jaxb-impl.jar jaxb-jxc.jar jaxb-xjc.jar; do local FQLIB="$BASE/jaxb-ri/lib/$LIB" if [[ -f $FQLIB ]]; then export CLASSPATH=$FQLIB:$CLASSPATH fi done } extend_qzminynshg; unset extend_qzminynshg 

¡Y funciona!

OK, he estado teniendo el mismo tipo de problema, pero estaba usando Java 8, y seguí recibiendo este error, probé la mayoría de las soluciones. pero resulta que mi experto todavía estaba apuntando a java 9, aunque configuré el java global como 8, así que tan pronto como resolví que todo funcionaba, para cualquier cuerpo que pudiera tener este tipo de problema, echa un vistazo (Cómo para arreglar Maven para usar Java por defecto) https://blog.tompawlak.org/maven-default-java-version-mac-osx