it-roy-ru.com

Как разрешить Java.lang.NoClassDefFoundError: javax/xml/bind/JAXBException в Java 9

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

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

493
Andy Guibert

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

Java 9 вводит понятия модулей, и по умолчанию агрегатный модуль Java.se доступен на пути к классам (или, скорее, на пути к модулям). Как следует из названия, агрегатный модуль Java.senot включает 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 доступными во время выполнения, указав параметр --add-modules Java.se.ee. Модуль Java.se.ee является агрегатным модулем, который включает в себя Java.se.ee, а также вышеупомянутые модули Java EE API.


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

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

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

<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: Модульная система

761
Andy Guibert

В моем случае (весенний загрузочный толстый кувшин) я просто добавляю следующее в pom.xml.

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

Ни одно из этих решений не помогло мне в недавнем выпуске 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>
57
Andremoniy

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

<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>

Gradle

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

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

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

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

Прекрасно работает до сих пор, как обходной путь. Не похоже на идеальное решение, хотя ...

35
Mikhail Kholodkov

это потому, что Java-версия, если вы используете JDK 9 или более позднюю версию, просто добавьте это в свой POM

<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.0</version>
</dependency>
18
Cesar Rodriguez T

Во время компиляции, а также во время выполнения, добавьте переключатель --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

15
Pallavi Sonal

Вы можете использовать опцию --add-modules=Java.xml.bind JVM, чтобы добавить модуль связывания xml в среду выполнения JVM.

Например: Java --add-modules=Java.xml.bind XmlTestClass

11
Jayesh Jayanthivasan

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

  • 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-апи-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-ядро-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-осущ-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. Скачайте вышеуказанные файлы и скопируйте их в папку libs в проекте
  2. Добавьте импортированные файлы JAR в Java Build Path
10
fnascimento

Перейдите в Your Build.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'
9
Kumar Abhishek

Это сработало для меня. Добавление только 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>
9
Mr Jedi

Для Java Web Start Execution мы можем использовать предложение Энди Гиберта, подобное этому:

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

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

8
mvw

чистое решение для всех JDK> = 9

Вам нужно добавить две зависимости в вашу сборку

  • jaxb-api
  • реализация Jaxb

В качестве реализации я решил использовать эталонную реализацию Glassfish, чтобы избавиться от старых классов/библиотек com.Sun . В результате я добавил в свою сборку 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>

Обратите внимание, что начиная с версии 2.3.1 вам больше не нужно добавлять javax.activation. (см. https://github.com/Eclipse-ee4j/jaxb-ri/issues/1222 )

7
Sebastian Thees

Следующий Какие артефакты я должен использовать для 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, скажем, Oxygen.3a Release (4.7.3a) или новее, Ctrl-Alt-P или щелкните правой кнопкой мыши проект Maven, затем выберите профиль.

7
JasonPlutext

Я следовал по этому 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>
4
itsraghz

добавить зависимость javax.xml.bind в pom.xml

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

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

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

3
Javide

Поскольку JavaEE теперь регулируется https://jakarta.ee/ , новые координаты Maven с 2.3.2:

https://github.com/Eclipse-ee4j/jaxb-ri#maven-artifacts

Первый выпущенный jaxb.version - 2.3.2.

<properties>
  <jaxb.version>2.3.2</jaxb.version>
</properties>

<dependency>
  <groupId>jakarta.xml.bind</groupId>
  <artifactId>jakarta.xml.bind-api</artifactId>
  <version>${jaxb.version}</version>
</dependency>
<dependency>
    <groupId>org.glassfish.jaxb</groupId>
    <artifactId>jaxb-runtime</artifactId>
    <version>${jaxb.version}</version>
</dependency>
3
dschulten

Не ответ, а дополнение: я получил, потому что запуск 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 на github.io ("JAXB лицензируется по двойной лицензии - CDDL 1.1 и GPL 2.0 с исключением пути к классам")

  • Скачать jaxb-ri-2.3.0.Zip

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

  • Убедитесь, что файлы jar в подкаталоге 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

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

2
David Tonhofer

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

1
Ipkiss

Старый ответ «Проблема решена переключением на amazoncorretto». Ответ в новостях: Я использовал самую последнюю версию corretto, но похож на jdk 1.8. так что в любом случае нам нужно добавить зависимости вручную

1
Armen Arzumanyan

Я знаю, что опаздываю на вечеринку, но моя ошибка закончилась тем, что мне нужно другое решение ... тоже очень просто

Изначально я деполировал на Tomcat 9 и понял, что мне нужно 7 ... Я забыл отобразить свой путь к классу обратно в 7 версию в build.xml

Надеюсь, это исправит ошибку кого-то еще в будущем, кому удастся пропустить эту простую проблему, как я!

0
Tyler Miles

Версии зависимостей, которые мне нужно было использовать при компиляции для цели Java 8. Протестировано приложение в Java 8, 11 и 12 JRE.

        <!-- replace dependencies that have been removed from JRE's starting with Java v11 -->
        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
            <version>2.2.8</version>
        </dependency>
        <dependency>
            <groupId>com.Sun.xml.bind</groupId>
            <artifactId>jaxb-core</artifactId>
            <version>2.2.8-b01</version>
        </dependency>
        <dependency>
            <groupId>com.Sun.xml.bind</groupId>
            <artifactId>jaxb-impl</artifactId>
            <version>2.2.8-b01</version>
        </dependency>
        <!-- end replace dependencies that have been removed from JRE's starting with Java v11 -->
0
Chris

Это сработало для меня, у меня есть весенний загрузочный проект, который компилируется в Java 8, но я не знаю, почему однажды мой maven начал компилировать с Java 11, в Ubuntu я использовал его для исправления:

Sudo update-Java-alternatives  -l

Это показало мне доступный JDK на моем компьютере:

Java-1.11.0-openjdk-AMD64      1111       /usr/lib/jvm/Java-1.11.0-openjdk-AMD64

Java-1.8.0-openjdk-AMD64 1081 /usr/lib/jvm/Java-1.8.0-openjdk-AMD64

Итак, я наконец запустил эту команду, чтобы выбрать желаемую:

Sudo update-Java-alternatives  -s Java-1.8.0-openjdk-AMD64 

И это все, чтобы больше взглянуть на Как использовать альтернативы команды update

0
AlvaroCachoperro