Вопрос-ответ

What causes and what are the differences between NoClassDefFoundError and ClassNotFoundException?

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

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

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

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

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


  1. пакеты, не включенные в build.xml для клиентской части кода

  2. отсутствует путь к классу среды выполнения для новых jar, которые мы используем

  3. версия конфликтует с предыдущей jar

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

Переведено автоматически
Ответ 1

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

Для ClassNotFoundException:


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



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

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

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


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


Для NoClassDefFoundError:


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


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


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

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

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

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

Ответ 2

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

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

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

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

При изучении кода, допустим, вы найдете строку кода, подобную приведенной ниже, убедитесь, что класс SomeClass in указан в вашем ПУТИ к КЛАССУ.

private static SomeClass foo = new SomeClass();

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

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

Ответ 3

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

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

Ответ 4

Ошибка NoClassDefFoundError (NCDFE) возникает, когда ваш код запускает "new Y ()" и не может найти класс Y.

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

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

класс a { 
статический класс b {}
public static void main(Строковые аргументы[]) {
System.out.println("Первая попытка создать b():");
try {new b(); } catch(Throwable t) {t.printStackTrace();}
System.out.println("\nSecond попытка создать b():");
try {new b(); } catch(Throwable t) {t.printStackTrace();}
}
}

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

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

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

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

Первая попытка new b():
java.lang.NoClassDefFoundError: a $ b
в 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)
в sun.разное.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 (генерируемому загрузчиком классов, когда он не может найти класс), который должен быть обернут в непроверенный NoClassDefFoundError , поскольку рассматриваемый код (new b()) должен просто работать.

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

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

java