JAXBException в Java 2025: как исправить NoClassDefFoundError

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Почему Java кричит «NoClassDefFoundError: javax/xml/bind/JAXBException» и что с этим делать в 2025?

Вы когда-нибудь сталкивались с ситуацией, когда ваше Java-приложение, которое ещё вчера работало как часы, сегодня падает с пугающей ошибкой java.lang.NoClassDefFoundError: javax/xml/bind/JAXBException? Если да — вы не одиноки. Этот вопрос собрал тысячи просмотров на Stack Overflow, и спрос на решение не падает даже в 2025 году. Дело в том, что проблема связана с фундаментальными изменениями в экосистеме Java, которые произошли несколько лет назад, но до сих пор аукаются разработчикам.

В этой статье мы не просто дадим «рыбу» — мы разберём, почему возникает эта ошибка, и покажем три надёжных способа её исправить. Вы узнаете, как правильно настроить Maven, Gradle или JVM-аргументы, чтобы ваше приложение снова заработало. Поехали!

Корень зла: Java 9 и модульная система

Всё началось с Java 9 (выпущенной в 2017 году). В этой версии Oracle внедрила модульную систему (Project Jigsaw). Многие пакеты, которые раньше были частью стандартной библиотеки (JDK), были вынесены в отдельные модули или удалены вовсе. Одним из таких «изгоев» стал пакет javax.xml.bind (JAXB — Java Architecture for XML Binding).

В Java 8 и старше JAXB был доступен «из коробки». Начиная с Java 9, он стал опциональным. А в Java 11 его и вовсе удалили из JDK. Если вы пишете код, который использует javax.xml.bind.JAXBContext, JAXBException или Marshaller, и запускаете его на Java 11+, вы гарантированно получите NoClassDefFoundError.

Важно: NoClassDefFoundError отличается от ClassNotFoundException. Первая возникает, когда класс был доступен на этапе компиляции, но исчез во время выполнения. Вторая — когда класс не найден вообще.

Сценарий: как выглядит проблема на практике

Представьте, что у вас есть простой класс для работы с XML:

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;

public class XmlProcessor {

    public void convertToXml(Object obj) throws JAXBException {
        JAXBContext context = JAXBContext.newInstance(obj.getClass());
        Marshaller marshaller = context.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
        // ... логика вывода
    }
}

Вы компилируете этот код на Java 8 — всё окей. Затем вы обновляете JDK до версии 11 или 17, запускаете приложение и видите:

Exception in thread "main" java.lang.NoClassDefFoundError: javax/xml/bind/JAXBException
    at XmlProcessor.convertToXml(XmlProcessor.java:6)
    ...

Знакомо? Теперь давайте решать.

Способ 1: Добавьте JAXB API как внешнюю зависимость (рекомендуемый)

Самый правильный и современный подход — явно указать, что ваше приложение использует JAXB. Для этого нужно подключить библиотеку через систему сборки (Maven или Gradle).

Для Maven (pom.xml)

Добавьте в <dependencies>:

<dependency>
    <groupId>jakarta.xml.bind</groupId>
    <artifactId>jakarta.xml.bind-api</artifactId>
    <version>4.0.2</version>
</dependency>
<dependency>
    <groupId>org.glassfish.jaxb</groupId>
    <artifactId>jaxb-runtime</artifactId>
    <version>4.0.5</version>
    <scope>runtime</scope>
</dependency>

Обратите внимание: с Jakarta EE 9 (июнь 2021) пакет javax.xml.bind переименован в jakarta.xml.bind. Если ваш код старый и использует javax.*, вы можете всё равно использовать jakarta.xml.bind-api — она прозрачно маппится. Но лучше обновить импорты в коде.

Для Gradle (build.gradle)

dependencies {
    implementation 'jakarta.xml.bind:jakarta.xml.bind-api:4.0.2'
    runtimeOnly 'org.glassfish.jaxb:jaxb-runtime:4.0.5'
}

После добавления зависимостей запустите сборку заново. NoClassDefFoundError исчезнет, потому что JAXB-классы теперь физически присутствуют в classpath.

Способ 2: Используйте JVM-аргумент --add-modules (для Java 9–10)

Этот способ подходит, если вы не можете менять код или систему сборки (например, работаете с легаси-проектом). Он работает на Java 9 и 10, но не работает на Java 11+, так как модуль был удалён.

Просто добавьте при запуске JVM флаг:

java --add-modules java.xml.bind -jar your-app.jar

Или, если вы запускаете из командной строки:

java --add-modules java.xml.bind -cp your-classpath MainClass

Этот флаг подключает модуль java.xml.bind из JDK. Но ещё раз: на Java 11+ модуля нет, поэтому вы получите ошибку «Module java.xml.bind not found».

Способ 3: Переход на альтернативу (JAXB → Jackson или SAX)

Иногда лучший способ решить проблему — не использовать JAXB вообще. В 2025 году это не самая популярная библиотека. Рассмотрите альтернативы:

  • Jackson XML — отлично работает с JSON и XML, активно поддерживается.
  • SAX / DOM / StAX — стандартные XML-парсеры, встроенные в JDK.
  • XStream — простая сериализация в XML.

Пример с Jackson XML (добавьте зависимость jackson-dataformat-xml):

import com.fasterxml.jackson.dataformat.xml.XmlMapper;

public class JacksonXmlProcessor {

    private final XmlMapper xmlMapper = new XmlMapper();

    public String toXml(Object obj) throws Exception {
        return xmlMapper.writeValueAsString(obj);
    }

    public <T> T fromXml(String xml, Class<T> clazz) throws Exception {
        return xmlMapper.readValue(xml, clazz);
    }
}

Этот код не зависит от JAXB и будет работать на любой версии Java.

Проверка версии Java и classpath

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

java -version

Если вы видите openjdk version "11"

Блоги

Рекомендаций по книгам