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

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

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

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

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

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

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

15 ответов


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

на ClassNotFoundException:

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

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

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

на NoClassDefFoundError:

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

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

Итак, похоже, что 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();

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

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


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

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 где-то!--13-->

код просто пытается создать экземпляр нового класса "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 без основной причины, вам нужно посмотреть, можете ли вы отследить до самого первого раза, когда класс был загружен, чтобы найти причину ошибки.


от 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.class file и запустить тестовый класс, он будет бросить

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 выдается

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

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

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


Разница Между ClassNotFoundException И 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

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

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

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


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

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

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


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

ClassNotFoundException

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

ClassNotFoundException extends ReflectiveOperationException extends Exception extends Throwable

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

  1. требуется jar, класс отсутствует в пути к классам.
  2. убедитесь, что все необходимые банки находятся в пути к классам 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 загрузить класс по его имени строки с помощью Class.forName () или ClassLoader.findSystemClass () или загрузчик классов.методы loadClass () и упомянутый класс не найдены в пути к классам.

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

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

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

enter image description here

вы можете узнать Все О ClassNotFoundException Против 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)