Какие причины и каковы различия между NoClassDefFoundError и ClassNotFoundException?

В чем разница между NoClassDefFoundError и ClassNotFoundException?

Что заставляет их бросать? Как они могут быть разрешены?

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

Возможные причины, по которым я столкнулся:

  • пакеты, не включенные в build.xml для клиентской части кода
  • пробел classpath отсутствует для новых банок, которые мы используем
  • конфликт версий с предыдущей банкой

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

+323
источник поделиться
15 ответов

Отличие от спецификаций Java API заключается в следующем.

Для ClassNotFoundException:

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

  • Метод forName в классе Class.
  • Метод findSystemClass в классе ClassLoader.
  • Метод loadClass в классе ClassLoader.

но определение для класса с указанное имя может быть найдено.

Для NoClassDefFoundError:

Брошено, если виртуальная машина Java или экземпляр ClassLoader пытается загрузить в определении класса (как часть обычного вызова метода или как часть создание нового экземпляра с использованием нового выражение), и определение класс.

Определенное определение класса существует, когда выполняемый в настоящее время класс был скомпилирован, но определение больше не может быть найден.

Итак, кажется, что NoClassDefFoundError возникает, когда источник был успешно скомпилирован, но во время выполнения необходимые файлы Class не были найдены. Это может быть что-то, что может произойти при распространении или выпуске JAR файлов, в которые были включены не все необходимые файлы Class.

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

Разница между двумя заключается в том, что один является Error, а другой - Exception. С NoClassDefFoundError является Error, и он возникает из-за того, что виртуальная машина Java испытывает проблемы с поиском класса, который он ожидал найти. Программа, которая должна была работать во время компиляции, не может выполняться из-за отсутствия файлов Class или не совпадает с тем, который был создан или встречен во время компиляции. Это довольно критическая ошибка, так как программа не может быть инициирована JVM.

С другой стороны, ClassNotFoundException является Exception, поэтому он несколько ожидается и является восстановимым. Использование рефлексии может быть подвергнуто ошибкам (так как есть некоторые ожидания, что все может идти не так, как ожидалось. Нет проверки времени компиляции, чтобы увидеть, что все необходимые классы существуют, поэтому любые проблемы с поиском нужных классов появятся во время выполнения.

+358
источник

Класс ClassNotFoundException генерируется, если класс ClassLoader не найден. Обычно это означает, что класс отсутствует в CLASSPATH. Это также может означать, что класс, о котором идет речь, пытается загрузить из другого класса, который был загружен в родительский загрузчик классов, и, следовательно, класс из дочернего загрузчика классов не отображается. Иногда это происходит при работе в более сложных средах, таких как сервер приложений (WebSphere является печально известным для таких проблем с загрузчиками классов).

Люди часто склонны путать java.lang.NoClassDefFoundError с java.lang.ClassNotFoundException, однако там важное различие. Например, исключение (ошибка действительно с java.lang.NoClassDefFoundError является подклассом java.lang.Error), например

java.lang.NoClassDefFoundError:
org/apache/activemq/ActiveMQConnectionFactory

не означает, что класс ActiveMQConnectionFactory отсутствует в CLASSPATH. Поразите его совсем наоборот. Это означает, что класс ActiveMQConnectionFactory был обнаружен ClassLoader, однако при попытке загрузить класс он столкнулся с ошибкой, читающей определение класса. Обычно это происходит, когда рассматриваемый класс имеет статические блоки или элементы, которые используют класс, который не найден ClassLoader. Поэтому, чтобы найти виновника, просмотрите источник рассматриваемого класса (в этом случае ActiveMQConnectionFactory) и найдите код, используя статические блоки или статические элементы. Если у вас нет доступа к источнику, просто декомпилируйте его с помощью JAD.

Изучив код, скажем, вы найдете строку кода, как показано ниже, убедитесь, что класс SomeClass включен в CLASSPATH.

private static SomeClass foo = new SomeClass();

Совет. Чтобы узнать, к какому классу принадлежит класс, вы можете использовать веб-сайт jarFinder. Это позволяет указать имя класса с помощью подстановочных знаков, и он ищет класс в своей базе данных банок. jarhoo позволяет вам делать то же самое, но его больше не использовать.

Если вы хотите найти, какой jar класс принадлежит локальному пути, вы можете использовать утилиту, такую ​​как jarscan (http://www.inetfeedback.com/jarscan/). Вы просто указываете класс, который хотите найти, и путь корневого каталога, где вы хотите, чтобы он начал поиск класса в банках и zip файлах.

+74
источник
другие ответы

Связанные вопросы


Похожие вопросы

NoClassDefFoundError - это ошибка связи. Это происходит, когда вы пытаетесь создать экземпляр объекта (статически с "новым" ), и он не найден, когда он был во время компиляции.

ClassNotFoundException является более общим и является исключением во время выполнения при попытке использовать класс, который не существует. Например, у вас есть параметр в функции, который принимает интерфейс, а кто-то передает класс, который реализует этот интерфейс, но у вас нет доступа к классу. Он также охватывает случай загрузки динамического класса, например, используя loadClass() или Class.forName().

+33
источник

A NoClassDefFoundError (NCDFE) происходит, когда ваш код запускает "новый Y()", и он не может найти класс Y.

Просто может быть, что Y отсутствует в вашем загрузчике классов, как и другие комментарии, но может быть, что Y-класс не подписан или имеет недопустимую подпись или что Y загружается другим загрузчиком классов на ваш код или даже на то, что Y зависит от Z, который не может быть загружен по какой-либо из вышеуказанных причин.

Если это произойдет, тогда JVM запомнит результат загрузки X (NCDFE), и он будет просто бросать новый NCDFE каждый раз, когда вы просите Y, не сообщая вам, почему:

class a {
  static class b {}
  public static void main(String args[]) {
    System.out.println("First attempt new b():");
    try {new b(); } catch(Throwable t) {t.printStackTrace();}
    System.out.println("\nSecond attempt new b():");
    try {new b(); } catch(Throwable t) {t.printStackTrace();}
  }
}

сохранить это как a.java где-нибудь

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

Скомпилируйте код с помощью javac a.java, затем запустите a, вызвав java -cp . a - он должен просто распечатать две строки текста, и он должен работать нормально без ошибок.

Затем удалите файл "a $b.class" (или залейте его мусором или скопируйте a.class поверх него), чтобы имитировать отсутствующий или поврежденный класс. Вот что происходит:

First attempt new b():
java.lang.NoClassDefFoundError: a$b
    at a.main(a.java:5)
Caused by: java.lang.ClassNotFoundException: a$b
    at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:252)
    at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:320)
    ... 1 more

Second attempt new b():
java.lang.NoClassDefFoundError: a$b
    at a.main(a.java:7)

Первый вызов приводит к исключению ClassNotFoundException (которое бросает загрузчик класса, когда он не может найти класс), который должен быть обернут в unchecked NoClassDefFoundError, так как этот код (new b()) должен просто работать.

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

Итак, если вы когда-либо видели NCDFE без основной причины, вам нужно увидеть, можете ли вы отследить назад в первый раз, когда класс был загружен, чтобы найти причину ошибки.

+27
источник

Из http://www.javaroots.com/2013/02/classnotfoundexception-vs.html:

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

NoClassDefFoundError: это сложнее отладить и найти причину. Это бросается, когда во время компиляции присутствуют требуемые классы, но во время выполнения классы изменяются или удаляются, или инициализация класса static исключает исключения. Это означает, что класс, который загружается, присутствует в пути к классам, но один из классов, которые требуются этому классу, либо удаляется, либо не загружается компилятором. Таким образом, вы должны увидеть классы, которые зависят от этого класса.

Пример:

public class Test1
{
}


public class Test 
{
   public static void main(String[] args)
   {
        Test1 = new Test1();    
   }

}

Теперь, после компиляции обоих классов, если вы удалите файл Test1.class и запустите тестовый класс, он бросит

Exception in thread "main" java.lang.NoClassDefFoundError: Test
    at Test1.main(Test1.java:5)
Caused by: java.lang.ClassNotFoundException: Test
    at java.net.URLClassLoader$1.run(Unknown Source)
    at java.net.URLClassLoader$1.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    ... 1 more

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

NoClassDefFoundError: вызывается, если виртуальная машина Java пытается загрузить в определение класса, и определение класса не может быть найдено.

+16
источник

В чем причина получения каждого из них и любого мыслительного процесса о том, как бороться с такими ошибками?

Они тесно связаны. A ClassNotFoundException вызывается, когда Java отправляется на поиск определенного класса по имени и не может его успешно загрузить. A NoClassDefFoundError бросается, когда Java отправляется на поиск класса, который был связан с каким-либо существующим кодом, но не мог найти его по той или иной причине (например, неправильный путь к классам, неправильная версия Java, неправильная версия библиотеки) и является полностью фатальным, поскольку это указывает на то, что что-то пошло плохо.

Если у вас есть фон C, CNFE похож на отказ dlopen()/dlsym(), а NCDFE - проблема с компоновщиком; во втором случае соответствующие файлы классов никогда не должны быть скомпилированы в конфигурации, которую вы пытаетесь использовать.

+13
источник

Пример # 1:

class A{
 void met(){
   Class.forName("com.example.Class1");
 }
}

Если com/example/Class1 не существует ни в одном из путей к классам, то он выбрасывает ClassNotFoundException.

Пример # 2:

Class B{
  void met(){
   com.example.Class2 c = new com.example.Class2();
 }
}

Если com/example/Class2 существовал при компиляции B, но не был обнаружен во время выполнения, тогда он выдает NoClassDefFoundError.

Оба являются исключениями времени выполнения.

+10
источник

ClassNotFoundException вызывается при попытке загрузить класс, ссылаясь на него через String. Например, параметр в Class.forName() является строкой, и это повышает потенциал недопустимых двоичных имен, передаваемых в загрузчик классов.

Класс ClassNotFoundException генерируется, когда встречается потенциально недействительное двоичное имя; например, если имя класса имеет символ "/", вы обязаны получить исключение ClassNotFoundException. Это также бросается, когда класс с прямой ссылкой недоступен в пути к классам.

С другой стороны, NoClassDefFoundError выбрано

  • когда фактическое физическое представление класса - файл .class недоступен,
  • или класс был загружен уже в другом загрузчике классов (обычно родительский загрузчик классов загружал класс и, следовательно, класс не мог быть загружен снова),
  • или если найдено несовместимое определение класса - имя в файле класса не соответствует запрашиваемому имени,
  • или (что наиболее важно), если зависимый класс не может быть расположен и загружен. В этом случае класс с прямой ссылкой мог быть размещен и загружен, но зависимый класс недоступен или не может быть загружен. Это сценарий, в котором класс с прямой ссылкой может быть загружен через Class.forName или эквивалентные методы. Это указывает на сбой в соединении.

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

В конце концов, до реализации класса ClassLoader требуется исключить экземпляр класса ClassNotFoundException, когда он не может загрузить класс. Большинство пользовательских реализаций загрузчика классов выполняют это, поскольку они расширяют URLClassLoader. Обычно загрузчики классов явно не выбрасывают NoClassDefFoundError для любой из реализаций метода - это исключение обычно выбрасывается из JVM в компиляторе HotSpot, а не самим загрузчиком классов.

+8
источник

Разница между ClassNotFoundException Vs NoClassDefFoundError

введите описание изображения здесь

+8
источник

С самими именами мы можем легко идентифицировать один из Exception, а другой - от Error.

Исключение: Исключения происходят во время выполнения программы. Программист может обработать это исключение блоком catch catch. У нас есть два типа исключений. Проверено исключение, которое выбрасывается во время компиляции. Исключения Runtime, которые выбрасываются во время выполнения, это исключение обычно происходит из-за плохого программирования.

Ошибка:. Это не исключение, оно выходит за рамки программиста. Эти ошибки обычно вызывают JVM.


введите описание изображения здесь источник изображения

Разница:

ClassNotFoundException:

  • загрузчик классов не может проверить класс байтов класса, который мы упоминаем в разделе Link подсистемы загрузки классов, мы получаем ClassNotFoundException.. li >
  • ClassNotFoundException - это проверенное исключение, полученное непосредственно из класса java.lang.Exception, и вам нужно предоставить явную обработку для него
  • ClassNotFoundException появляется при наличии явной загрузки класса, предоставляя имя класса во время выполнения с использованием ClassLoader.loadClass(), Class.forName() и ClassLoader.findSystemClass().

NoClassDefFoundError:

  • При загрузке класса разрешать ссылки класса Фаза связи подсистемы загрузки классов мы получаем NoClassDefFoundError.
  • NoClassDefFoundError - это ошибка, полученная из класса LinkageError, которая используется для указания ошибок, когда класс имеет зависимость от какого-либо другого класса, и этот класс несовместимо изменил после компиляции.
  • NoClassDefFoundError является результатом неявной загрузки класса из-за вызова метода из этого класса или любого доступа к переменной.

Сходства:

  • Оба NoClassDefFoundError и ClassNotFoundException связаны с недоступностью класса во время выполнения.
  • Оба ClassNotFoundException и NoClassDefFoundError относятся к пути Java classpath.
+4
источник

Учитывая действия sussystem загрузчика класса:

http://www.artima.com/insidejvm/ed2/images/fig7-1.gif

Это статья, которая помогла мне понять разницу: http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-5.html

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

Если виртуальная машина Java пытается загрузить класс C во время проверка (§5.4.1) или разрешение (§5.4.3) (но не инициализация (§5.5)) и загрузчик классов, который используется для инициирования загрузки C выдает экземпляр ClassNotFoundException, затем виртуальный Java Машина должна выдать экземпляр NoClassDefFoundError, причиной которого является экземпляр ClassNotFoundException.

Итак, ClassNotFoundException является основной причиной NoClassDefFoundError.
И NoClassDefFoundError является особым случаем ошибки загрузки типа, которая встречается на шаге Связывание.

+3
источник

Добавьте на практике одну возможную причину:

  • ClassNotFoundException: как сказал cletus, вы используете интерфейс, в то время как унаследованный класс интерфейса не находится в пути к классам. Например, шаблон поставщика услуг (или "Локатор сервисов" ) попытайтесь найти какой-то несуществующий класс
  • NoClassDefFoundError: данный класс найден, пока зависимость данного класса не найдена

На практике Ошибка может быть выбрано без помех, например, вы отправляете задание таймера, а в задаче таймера он выдает Ошибка, тогда как в большинстве случаев ваша программа получает только Исключение. Затем основной цикл Таймер завершается без какой-либо информации. Аналогичная ошибка NoClassDefFoundError ExceptionInInitializerError, когда ваш статический инициализатор или инициализатор для статической переменной генерирует исключение.

+2
источник

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

В большинстве случаев это исключение возникает при попытке запустить приложение без обновления пути к классам с требуемыми файлами JAR. Например, возможно, вы видели это исключение, когда код JDBC подключается к вашей базе данных i.e.MySQL, но ваш путь к классу не имеет JAR для него.

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

Ниже приведено краткое описание

введите описание изображения здесь

Вы можете прочитать Все о ClassNotFoundException Vs NoClassDefFoundError для более подробной информации.

+1
источник

Я снова и снова повторяю, когда мне нужно обновить

ClassNotFoundException

Иерархия классов

ClassNotFoundException extends ReflectiveOperationException extends Exception extends Throwable

При отладке

  • Необходимый jar, класс отсутствует в пути к классам.
  • Убедитесь, что все необходимые банки находятся в пути класса jvm.

NoClassDefFoundError

Иерархия классов

NoClassDefFoundError extends LinkageError  extends Error extends Throwable

При отладке

  • Проблема с динамической загрузкой класса, который был скомпилирован правильно
  • Проблема со статическими блоками, конструкторами, методами init() зависимого класса и фактической ошибкой обернута несколькими слоями [особенно когда вы используете spring, спящий режим фактическое исключение завернуто, и вы получите NoClassDefError]
  • Когда вы сталкиваетесь с "ClassNotFoundException" под статическим блоком зависимого класса
  • Проблема с версиями класса. Это происходит, когда у вас есть две версии v1, v2 одного и того же класса в разных jar/packages, которые были скомпилированы успешно с использованием v1 и v2, загружаются во время выполнения, которое не имеет соответствующих методов /vars & вы увидите это исключение. [Я как-то разрешил эту проблему, удалив дубликат связанного с log4j класса в нескольких баночках, появившихся в пути к классам]
0
источник

ClassNotFoundException и NoClassDefFoundError возникают, когда определенный класс не найден во время выполнения. Однако они встречаются в разных сценариях.

ClassNotFoundException - это исключение, возникающее при попытке загрузить класс во время выполнения с использованием методов Class.forName() или loadClass(), а упомянутые классы не найдены в пути к классам.

    public class MainClass
    {
        public static void main(String[] args)
        {
            try
            {
                Class.forName("oracle.jdbc.driver.OracleDriver");
            }catch (ClassNotFoundException e)
            {
                e.printStackTrace();
            }
        }
    }



    java.lang.ClassNotFoundException: oracle.jdbc.driver.OracleDriver
    at java.net.URLClassLoader.findClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Unknown Source)
    at pack1.MainClass.main(MainClass.java:17)

NoClassDefFoundError - это ошибка, которая возникает, когда определенный класс присутствует во время компиляции, но отсутствовал во время выполнения.

    class A
    {
      // some code
    }
    public class B
    {
        public static void main(String[] args)
        {
            A a = new A();
        }
    }

При компиляции вышеуказанной программы создаются два .class файла. Один из них - A.class, а другой - B.class. Если вы удалите файл A.class и запустите файл B.class, Java Runtime System вызовет NoClassDefFoundError, как показано ниже:

    Exception in thread "main" java.lang.NoClassDefFoundError: A
    at MainClass.main(MainClass.java:10)
    Caused by: java.lang.ClassNotFoundException: A
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
0
источник

Посмотрите другие вопросы по меткам или Задайте вопрос