Рубрики
Без рубрики

Исключение ClassNotFoundException против NoClassDefFoundError

Узнайте о различиях между ClassNotFoundException и NoClassDefFoundError.

Автор оригинала: baeldung.

1. введение

Оба ClassNotFoundException и NoClassDefFoundError возникают, когда JVM не может найти запрошенный класс в пути к классам. Хотя они выглядят знакомыми, между этими двумя есть некоторые основные различия.

В этом уроке мы обсудим некоторые причины их возникновения и их решения.

2. Исключение ClassNotFoundException

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

Это происходит в основном при попытке загрузить классы с помощью Class.forName() , ClassLoader.loadClass() или ClassLoader.findSystemClass() . Поэтому нам нужно быть особенно осторожными с java.lang.Исключение ClassNotFoundException при работе с отражением.

Например, давайте попробуем загрузить класс драйвера JDBC без добавления необходимых зависимостей, которые приведут к исключению ClassNotFoundException:

@Test(expected = ClassNotFoundException.class)
public void givenNoDrivers_whenLoadDriverClass_thenClassNotFoundException() 
  throws ClassNotFoundException {
      Class.forName("oracle.jdbc.driver.OracleDriver");
}

3. NoClassDefFoundError

NoClassDefFoundError является фатальной ошибкой. Это происходит, когда JVM не может найти определение класса при попытке:

  • Создайте экземпляр класса с помощью ключевого слова new
  • Загрузите класс с помощью вызова метода

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

Давайте рассмотрим сценарий, который является одним из простых способов воспроизвести проблему. Класс в нем ошибается инициализация создает исключение. Поэтому, когда мы пытаемся создать объект класса В нем Возникают ошибки, он выдает exceptioninitializererror.

Если мы попытаемся снова загрузить тот же класс, мы получим NoClassDefFoundError:

public class ClassWithInitErrors {
    static int data = 1 / 0;
}
public class NoClassDefFoundErrorExample {
    public ClassWithInitErrors getClassWithInitErrors() {
        ClassWithInitErrors test;
        try {
            test = new ClassWithInitErrors();
        } catch (Throwable t) {
            System.out.println(t);
        }
        test = new ClassWithInitErrors();
        return test;
    }
}

Давайте напишем тестовый пример для этого сценария:

@Test(expected = NoClassDefFoundError.class)
public void givenInitErrorInClass_whenloadClass_thenNoClassDefFoundError() {
 
    NoClassDefFoundErrorExample sample
     = new NoClassDefFoundErrorExample();
    sample.getClassWithInitErrors();
}

4. Разрешение

Иногда диагностика и устранение этих двух проблем может занять довольно много времени. Основной причиной обеих проблем является недоступность файла класса (в пути к классу) во время выполнения.

Давайте рассмотрим несколько подходов, которые мы можем рассмотреть при работе с любым из них:

  1. Нам нужно убедиться, доступен ли класс или jar, содержащий этот класс, в пути к классу. Если нет, нам нужно добавить его
  2. Если он доступен в пути к классам приложения, то, скорее всего, путь к классам переопределяется. Чтобы исправить это, нам нужно найти точный путь к классу, используемый нашим приложением
  3. Кроме того, если приложение использует несколько загрузчиков классов, классы, загруженные одним загрузчиком классов, могут быть недоступны другим загрузчикам классов. Чтобы устранить неполадки, необходимо знать как загрузчики классов работают в Java

5. Краткое изложение

Хотя оба эти исключения связаны с тем, что путь к классам и среда выполнения Java не могут найти класс во время выполнения, важно отметить их различия.

Среда выполнения Java выдает ClassNotFoundException при попытке загрузить класс только во время выполнения, и имя было указано во время выполнения. В случае NoClassDefFoundError класс присутствовал во время компиляции, но среда выполнения Java не смогла найти его в пути к классам Java во время выполнения.

Как всегда, полный код для всех примеров можно найти на GitHub .