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

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

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

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

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

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

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

    15 Solutions collect form web for “Какие причины и каковы различия между NoClassDefFoundError и ClassNotFoundException?”

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

    Для ClassNotFoundException :

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

    • Метод forName в classе Class .
    • Метод findSystemClass в classе ClassLoader .
    • Метод loadClass в classе ClassLoader .

    но определение classа с указанным именем не найдено.

    Для NoClassDefFoundError :

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

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

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

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

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

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

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

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

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

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

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

     private static SomeClass foo = new SomeClass(); 

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

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

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

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

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

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

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

     class a {
       статический class b {}
       public static void main (String args []) {
         System.out.println («Первая попытка new b ():»);
         попробуйте {new b ();  } catch (Throwable t) {t.printStackTrace ();}
         System.out.println ("\ nВсегда попытка new b ():");
         попробуйте {new b ();  } catch (Throwable t) {t.printStackTrace ();}
       }
     }
    

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

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

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

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

     Первая попытка new b ():
     java.lang.NoClassDefFoundError: a $ b
         at a.main (a.java:5)
     Вызывается: java.lang.ClassNotFoundException: a $ b
         на java.net.URLClassLoader $ 1.run (URLClassLoader.java:200)
         в java.security.AccessController.doPrivileged (собственный метод)
         в java.net.URLClassLoader.findClass (URLClassLoader.java:188)
         в java.lang.ClassLoader.loadClass (ClassLoader.java.307)
         at sun.misc.Launcher $ AppClassLoader.loadClass (Launcher.java:301)
         в java.lang.ClassLoader.loadClass (ClassLoader.java:252)
         в java.lang.ClassLoader.loadClassInternal (ClassLoader.java:320)
         ... 1 более
    
     Вторая попытка new b ():
     java.lang.NoClassDefFoundError: a $ b
         на a.main (a.java:7)
    

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

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

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

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

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

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

    Пример :

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

    Теперь, после компиляции обоих classов, если вы удалите файл Test1.class и запустите тестовый 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 : бросается, когда приложение пытается загрузить в class через его имя, но определение classа с указанным именем не найдено.

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

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

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

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

    Пример №1:

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

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

    Пример №2:

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

    Разница:

    ClassNotFoundException:

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

    NoClassDefFoundError:

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

    сходства:

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

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

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

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

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

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

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

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

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

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

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

    ClassNotFoundException

    Иерархия classов

     ClassNotFoundException extends ReflectiveOperationException extends Exception extends Throwable 

    При отладке

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

    NoClassDefFoundError

    Иерархия classов

     NoClassDefFoundError extends LinkageError extends Error extends Throwable 

    При отладке

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

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

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

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

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

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

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

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

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

      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 присутствует во время компиляции, но во время выполнения отсутствует.

      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) 
    Давайте будем гением компьютера.