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


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

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

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

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

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

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

15 342

15 ответов:

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

на ClassNotFoundException:

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

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

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

на NoClassDefFoundError:

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

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

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

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

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

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

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

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

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

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

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

private static SomeClass foo = new SomeClass();

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

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

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

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

NoClassDefFoundError (NCDFE) происходит, когда ваш код запускает "new 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.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 (брошенному загрузчиком класса, когда он не может найти класс), который должен быть обернут в непроверенный NoClassDefFoundError, так как рассматриваемый код (new b()) должны просто работать.

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

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

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

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

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

пример:

public class Test1
{
}


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

}

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

Exception in thread "main" java.lang.NoClassDefFoundError: Test
    at Test1.main(Test1.java:5)
Caused by: java.lang.ClassNotFoundException: Test
    at java.net.URLClassLoader.run(Unknown Source)
    at java.net.URLClassLoader.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 пытается загрузить в определении класса, и никакое определение класса не может быть найдено.

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

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

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

Пример 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.

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

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

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

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

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

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

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

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

enter image description here

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

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

ошибка:

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

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

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

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

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

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

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

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

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

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

ClassNotFoundException

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

ClassNotFoundException extends ReflectiveOperationException extends Exception extends Throwable

во время отладки

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

NoClassDefFoundError

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

NoClassDefFoundError extends LinkageError  extends Error extends Throwable

во время отладки

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

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

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

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

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

enter image description here

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

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

ClassNotFoundException исключение, возникающее при попытке загрузить класс во время выполнения с помощью класса.методы 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();
        }
    }

при компиляции вышеуказанной программы, два .будут созданы файлы классов. Один из них 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)