Как решить java.ленг.NoClassDefFoundError: javax / xml / bind / JAXBException в Java 9



У меня есть некоторый код, который использует классы API JAXB, которые были предоставлены как часть JDK в Java 6/7/8. Когда я запускаю тот же код с Java 9, во время выполнения я получаю ошибки, указывающие, что классы JAXB не могут быть найдены.



классы JAXB были предоставлены как часть JDK с Java 6, так почему Java 9 больше не может найти эти классы?

660   15  

15 ответов:

API JAXB считаются API Java EE, и поэтому больше не содержатся на пути к классу по умолчанию в Java SE 9. В Java 11 они полностью удалены из JDK.

Java 9 вводит понятия модулей, и по умолчанию java.se модуль aggregate доступен на пути к классу (или, скорее, пути к модулю). Как следует из названия,java.se агрегатный модуль делает не включите API Java EE, которые традиционно были в комплекте с Java 6/7/8.

к счастью, эти API Java EE, которые были предоставлены в JDK 6/7/8, все еще находятся в JDK, но они просто не находятся на пути к классу по умолчанию. Дополнительные API Java EE предоставляются в следующих модулях:

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

быстрое и грязное решение: (только JDK 9/10)
Чтобы сделать API JAXB доступными во время выполнения, укажите следующий параметр командной строки:
--add-modules java.xml.bind

но мне все еще нужно, чтобы это работало с Java 8!!!
Если вы попытаетесь указать --add-modules С более старым JDK он взорвется, потому что это непризнанный вариант. Я предлагаю один из двух вариантов:

  1. вы можете условно применить аргумент в сценарии запуска (если он у вас есть), проверив версию JDK, проверив $JAVA_HOME/release на JAVA_VERSION собственность.
  2. вы можете добавить -XX:+IgnoreUnrecognizedVMOptions чтобы заставить JVM молча игнорировать нераспознанные параметры, вместо того, чтобы взорваться. Но будьте осторожны! Любой другой аргументы командной строки, которые вы используете, больше не будут проверяться для вас JVM. Эта опция работает с Oracle / OpenJDK, а также IBM JDK (начиная с JDK 8sr4)

альтернативное быстрое решение: (только JDK 9/10)
Обратите внимание, что вы можете сделать все вышеперечисленные модули Java EE доступными во время выполнения, указав . Элемент java.se.ee модуль-это агрегатный модуль, который включает java.se.ee а также выше Java EE API модули.


правильное долгосрочное решение: (все версии JDK)

все перечисленные выше модули API Java EE отмечены @Deprecated(forRemoval=true), потому что они запланировано на на Java 11. Так что --add-module подход не будет работать в Java 11 из коробки.

что вам нужно будет сделать в Java 11 и вперед, это включить свою собственную копию API Java EE на пути к классу или модулю путь. Например, вы можете добавить API JAX-B в качестве зависимости maven следующим образом:

<!-- Java 6 = JAX-B Version 2.0   -->
<!-- Java 7 = JAX-B Version 2.2.3 -->
<!-- Java 8 = JAX-B Version 2.2.8 -->
<dependency>
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
    <version>2.2.11</version>
</dependency>
<dependency>
    <groupId>com.sun.xml.bind</groupId>
    <artifactId>jaxb-core</artifactId>
    <version>2.2.11</version>
</dependency>
<dependency>
    <groupId>com.sun.xml.bind</groupId>
    <artifactId>jaxb-impl</artifactId>
    <version>2.2.11</version>
</dependency>
<dependency>
    <groupId>javax.activation</groupId>
    <artifactId>activation</artifactId>
    <version>1.1.1</version>
</dependency>

для получения полной информации о модульности Java см. JEP 261: модульная система

в моем случае (spring boot fat jar) я просто добавляю следующее в pom.XML.

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

ни одно из этих решений работал для меня в последние JDK версии 9.0.1.

я обнаружил, что этот список зависимостей достаточно для правильного функционирования, так что вы не нужно явно указать --add-module (хотя это указано в POM этих зависимостей). Единственное, что вам нужно, это указать список зависимостей:

<dependencies>
    <dependency>
        <groupId>javax.xml.bind</groupId>
        <artifactId>jaxb-api</artifactId>
        <version>2.3.0</version>
    </dependency>
    <dependency>
        <groupId>com.sun.xml.bind</groupId>
        <artifactId>jaxb-impl</artifactId>
        <version>2.3.0</version>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jaxb</groupId>
        <artifactId>jaxb-runtime</artifactId>
        <version>2.3.0</version>
    </dependency>
    <dependency>
        <groupId>javax.activation</groupId>
        <artifactId>activation</artifactId>
        <version>1.1.1</version>
    </dependency>
</dependencies>

это сработало для меня:

<dependency>
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
    <version>2.3.0</version>
</dependency>
<dependency>
    <groupId>org.eclipse.persistence</groupId>
    <artifactId>eclipselink</artifactId>
    <version>2.7.0</version>
</dependency>

обновление

как предложил @Jasper, чтобы избежать зависимости от всей библиотеки EclipseLink, вы также можете просто зависеть от EclipseLink MOXy:

Maven

<dependency>
    <groupId>org.eclipse.persistence</groupId>
    <artifactId>org.eclipse.persistence.moxy</artifactId>
    <version>2.7.3</version>
</dependency>

ш

compile group: 'org.eclipse.persistence', name: 'org.eclipse.persistence.moxy', version: '2.7.3'

как зависимости для моего приложения Java 8, которое производит *.jar, который может быть запущен как JRE 8, так и JRE 9 без дополнительных аргументов.

In кроме того, это должно быть выполнено где-то перед использованием JAXB API:

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

отлично работает до сих пор, как обходной путь. Не выглядит идеальным решением...

во время компиляции, а также во время выполнения добавьте переключатель --add-modules java.xml.bind

javac --add-modules java.xml.bind <java file name>

java --add-modules java.xml.bind <class file>

хорошее введение JDK 9 модули также можно найти по адресу : https://www.youtube.com/watch?v=KZfbRuvv5qc

можно использовать JVM, чтобы добавить модуль XML привязки к JVM во время выполнения окружающей среды.

например: java --add-modules=java.xml.bind XmlTestClass

чтобы решить эту проблему, я импортировал некоторые файлы JAR в мой над файлами и скопируйте их в папку libs в проекте

  • добавить импортированные файлы JAR в Java Build Path
  • для выполнения Java Web Start мы можем использовать предложение Энди Гиберта следующим образом:

    <j2se version="1.6+" 
          java-vm-args="-XX:+IgnoreUnrecognizedVMOptions --add-modules=java.se.ee"/>
    

    обратите внимание на дополнительный " = " в --add-modules. Смотрите этот билет OpenJDK или последняя заметка в разделе "понимание предупреждений о доступе во время выполнения"Java Platform, Standard Edition Oracle JDK 9 руководство по миграции.

    это сработало для меня. Добавление только JAXB-api было недостаточно.

            <dependency>
                <groupId>javax.xml.bind</groupId>
                <artifactId>jaxb-api</artifactId>
                <version>${jaxb-api.version}</version>
            </dependency>
            <dependency>
                <groupId>com.sun.xml.bind</groupId>
                <artifactId>jaxb-impl</artifactId>
                <version>${jaxb-api.version}</version>
            </dependency>
            <dependency>
                <groupId>com.sun.xml.bind</groupId>
                <artifactId>jaxb-core</artifactId>
                <version>${jaxb-api.version}</version>
            </dependency>
    

    перейдите к своей сборке.gradle и добавить ниже зависимости для Java 9 или 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'
    

    после какие артефакты следует использовать для JAXB RI в моем проекте Maven? в Maven, вы можете использовать профиль типа:

    <profile>
        <id>java-9</id>
        <activation>
            <jdk>9</jdk>
        </activation>
        <dependencies>
            <dependency>
                <groupId>org.glassfish.jaxb</groupId>
                <artifactId>jaxb-runtime</artifactId>
                <version>2.3.0</version>
            </dependency>
            <dependency>
                <groupId>javax.activation</groupId>
                <artifactId>activation</artifactId>
                <version>1.1.1</version>
            </dependency>
        </dependencies>
    </profile> 
    

    дерево зависимостей показывает:

    [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
    

    чтобы использовать это в Eclipse, скажем, кислород.3a Release (4.7.3 a) или более поздней версии, Ctrl-Alt-P или щелкните правой кнопкой мыши на проекте Maven, затем выберите профиль.

    не ответ, а дополнение: я получил, потому что работает groovysh (Groovy 2.4.13) если JAVA_HOME указывает на установку Java 9 (java version "9.0.1" если быть точным) терпит неудачу ужасно:

    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.<init>(Groovysh.groovy:135)
            at org.codehaus.groovy.vmplugin.v7.IndyInterface.selectMethod(IndyInterface.java:232)
            at org.codehaus.groovy.tools.shell.Main.<init>(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
    

    решение было:

    • перейти к проект JAXB at github.io ( "JAXB лицензируется под двойной лицензией-CDDL 1.1 и GPL 2.0 с исключением пути к классу")

    • скачать jaxb-ri-2.3.0.zip

    • распакуйте везде, где вы помещаете свои файлы инфраструктуры java (в моем случае,/usr/local/java/jaxb-ri/). Другое решение может существовать (возможно, через SDKMAN, я не знаю)

    • убедитесь, что банки в подкаталоге lib на CLASSPATH. Я делаю это с помощью скрипта, запущенного при запуске bash, под названием /etc/profile.d/java.sh, где я добавил (среди многих других линий) следующий цикл:

    упаковано в функцию...

    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
    

    и это работает!

    Я следил за этим URL-адресом, и приведенные ниже настройки действительно помогли мне. Я использую Java 10 с STS IDE в Macbook Pro. Это работает как шарм.

       <dependency>
        <groupId>javax.xml.bind</groupId>
        <artifactId>jaxb-api</artifactId>
        <version>2.3.0</version>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jaxb</groupId>
        <artifactId>jaxb-runtime</artifactId>
        <version>2.3.0</version>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>javax.activation</groupId>
        <artifactId>javax.activation-api</artifactId>
        <version>1.2.0</version>
    </dependency>
    

    хорошо, у меня была такая же проблема, но я использовал java 8 и продолжал получать эту ошибку, я пробовал большинство решений. но оказывается, что мой maven все еще указывал на java 9, хотя я установил глобальную java как 8, поэтому, как только я исправил, что все это сработало, для любого тела, у которого может быть такая проблема, проверьте (как исправить Maven для использования Java по умолчанию ) https://blog.tompawlak.org/maven-default-java-version-mac-osx

    я столкнулся с той же проблемой, используя Spring Boot 2.0.5.RELEASE на Java 11.

    добавлять javax.xml.bind:jaxb-api:2.3.0 в одиночку не решить эту проблему. Мне также пришлось обновить Spring Boot до последней вехи 2.1.0.M2, Так что я предполагаю, что это будет исправлено в следующем официальном релизе.

    Comments

      Ничего не найдено.