Avatar ·

Как исправить java.lang.NoClassDefFoundError: javax/xml/bind/JAXBException в Java 9, 10, 11?

Всем привет! Я начинающий Java-разработчик, пишу простое приложение для работы с XML. Использую JAXB для преобразования объектов в XML и обратно. Раньше всё работало отлично на Java 8, но после перехода на Java 11 при запуске получаю ошибку:

Exception in thread "main" java.lang.NoClassDefFoundError: javax/xml/bind/JAXBException

Вот мой код:

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

public class XmlConverter {
    public static void main(String[] args) {
        try {
            JAXBContext context = JAXBContext.newInstance(User.class);
            Marshaller marshaller = context.createMarshaller();
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            
            User user = new User("Иван", 25);
            marshaller.marshal(user, System.out);
        } catch (JAXBException e) {
            e.printStackTrace();
        }
    }
}

class User {
    private String name;
    private int age;
    
    // геттеры, сеттеры, конструктор...
}

Я использую:

  • Java 11 (OpenJDK)
  • Maven для сборки
  • Никаких дополнительных зависимостей не подключал

Почему это происходит? Ведь на Java 8 всё работало! Мне нужно срочно починить проект, подскажите, как это исправить?

<<>>

Почему возникает ошибка?

Начиная с Java 9 модуль java.xml.bind (который содержит JAXB API) был помечен как устаревший (deprecated) и по умолчанию исключён из classpath. В Java 11 он и вовсе удалён из стандартной поставки JDK. Это сделано в рамках модульной системы Java (Project Jigsaw).

Раньше JAXB входил в состав JDK (Java SE), но теперь его нужно подключать отдельно как внешнюю библиотеку.

Решение №1: Добавить JAXB как Maven-зависимость (рекомендуется)

Добавьте в ваш pom.xml следующие зависимости:

<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>
<dependency>
    <groupId>javax.activation</groupId>
    <artifactId>javax.activation-api</artifactId>
    <version>1.2.0</version>
</dependency>

Пояснение:

  • jaxb-api — содержит интерфейсы и аннотации JAXB
  • jaxb-runtime — реализация от GlassFish (можно использовать и Eclipse Implementation — org.eclipse.persistence:org.eclipse.persistence.moxy)
  • javax.activation-api — нужен для корректной работы JAXB в Java 11+

Решение №2: Для Gradle

implementation 'javax.xml.bind:jaxb-api:2.3.1'
implementation 'org.glassfish.jaxb:jaxb-runtime:2.3.1'
implementation 'javax.activation:javax.activation-api:1.2.0'

Решение №3: Использовать --add-modules (только для Java 9-10)

Если вы временно работаете на Java 9 или 10, можно добавить флаги JVM. Но это не сработает на Java 11+:

--add-modules java.xml.bind

Решение №4: Откатиться на Java 8 (не рекомендуется)

Можно просто использовать Java 8, где JAXB всё ещё встроен. Но это временное решение — Java 8 уже не получает обновлений безопасности.

Проверка после исправления

После добавления зависимостей запустите Maven clean install:

mvn clean compile

Ошибка должна исчезнуть. Если нет — проверьте, что зависимости действительно загрузились (папка .m2/repository).

Важно!

Если вы используете Java 17 или новее, рекомендую рассмотреть переход на Jakarta XML Binding (новое имя JAXB после передачи в Eclipse Foundation):

<dependency>
    <groupId>jakarta.xml.bind</groupId>
    <artifactId>jakarta.xml.bind-api</artifactId>
    <version>4.0.0</version>
</dependency>
<dependency>
    <groupId>com.sun.xml.bind</groupId>
    <artifactId>jaxb-impl</artifactId>
    <version>4.0.0</version>
</dependency>

И импорты заменятся с javax.xml.bind.* на jakarta.xml.bind.*.

<<>>

Альтернативный подход: Использовать Jackson для работы с XML

Если вы не привязаны именно к JAXB, можно полностью отказаться от него и использовать более современную библиотеку Jackson. Она имеет схожий функционал, но лучше поддерживается в новых версиях Java.

Пример с Jackson XML:

// Добавьте в pom.xml:
// com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.15.2

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

public class JacksonXmlExample {
    public static void main(String[] args) throws Exception {
        XmlMapper mapper = new XmlMapper();
        User user = new User("Петр", 30);
        
        // Сериализация в XML
        String xml = mapper.writerWithDefaultPrettyPrinter()
                          .writeValueAsString(user);
        System.out.println(xml);
        
        // Десериализация из XML
        User deserialized = mapper.readValue(xml, User.class);
    }
}

Плюсы Jackson:

  • Не требует дополнительных модулей JVM
  • Работает на всех версиях Java (8, 11, 17, 21)
  • Единый API для JSON, XML, YAML и других форматов
  • Активно поддерживается сообществом

Минусы:

  • Может потребоваться рефакторинг кода
  • Некоторые специфические возможности JAXB (например, @XmlTransient) реализованы иначе

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