Как устранить java.lang.NoClassDefFoundError: javax/xml/bind/JAXBException
У меня есть код, который использует классы API JAXB, предоставленные в составе JDK в Java 6/7/8. Когда я запускаю тот же код с Java 9, во время выполнения я получаю ошибки, указывающие на то, что классы JAXB не могут быть найдены.
Классы JAXB были включены в состав JDK с Java 6, так почему же в Java 9 эти классы больше не могут быть обнаружены?
5 ответ(ов)
В вашем случае (фет-джар Spring Boot) нужно просто добавить следующий код в ваш файл pom.xml
:
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
Это позволит вам использовать JAXB API в вашем приложении.
Чистое решение для всех 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)
Ни одно из предложенных решений не сработало для меня в актуальной версии 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>
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");
Пока все работает отлично в качестве временного решения. Хотя это не выглядит как идеальный вариант...
Это связано с версией Java. Если вы используете JDK 9 или более позднюю версию, просто добавьте это в ваш pom.xml
:
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.0</version>
</dependency>
Это должно решить проблему.
Инициализация ArrayList в одну строчку
Как работают сервлеты? Инстанцирование, сессии, общие переменные и многопоточность
Java 8: Преобразование List<V> в Map<K, V>
Возможные значения конфигурации hbm2ddl.auto в Hibernate и их назначение
Что такое PECS (Producer Extends Consumer Super)?