В чем разница между NoClassDefFoundError
и ClassNotFoundException
?
Что заставляет их быть брошенными? Как они могут быть решены?
Я часто сталкиваюсь с этими throwables при изменении существующего кода, чтобы включить новые файлы JAR. Я ударил их как на стороне клиента, так и на стороне сервера для Java-приложения, распространяемого через веб-запуск.
Возможные причины, с которыми я столкнулся:
- пакеты не включены
build.xml
для клиентской части кода - путь к классу во время выполнения отсутствует для новых банок, которые мы используем
- версия конфликтует с предыдущей флягой
Когда я сталкиваюсь с этим сегодня, я использую метод «след и ошибка», чтобы все заработало. Мне нужно больше ясности и понимания.
-verbose
(например-verbose:class -verbose:jni
) справок - но ниже в своем ответе моги сообщают, что это не дает никакой дополнительной полезной информации :(Ответы:
Отличие от спецификаций API Java заключается в следующем.
Для
ClassNotFoundException
:Для
NoClassDefFoundError
:Итак, похоже, что это
NoClassDefFoundError
происходит, когда исходный код был успешно скомпилирован, но во время выполнения необходимыеclass
файлы не были найдены. Это может произойти при распространении или создании файлов JAR, где не все необходимыеclass
файлы были включены.Что касается
ClassNotFoundException
, кажется, что это может произойти из-за попыток сделать рефлексивные вызовы к классам во время выполнения, но классов, которые пытается вызвать программа, не существует.Разница между ними заключается в том, что один - это
Error
а другой -Exception
. СNoClassDefFoundError
являетсяError
и это происходит из-за виртуальной машины Java, имеющей проблемы с поиском класса, который она ожидала найти. Программа, которая должна была работать во время компиляции, не может быть запущена из-за того, чтоclass
файлы не найдены или не совпадает с той, которая была создана или обнаружена во время компиляции. Это довольно критическая ошибка, так как JVM не может инициировать программу.С другой стороны,
ClassNotFoundException
этоException
, так что это несколько ожидаемо, и это то, что можно восстановить. Использование рефлексии может быть подвержено ошибкам (так как есть некоторые ожидания, что все может пойти не так, как ожидалось. Нет проверки во время компиляции, чтобы увидеть, что все необходимые классы существуют, поэтому любые проблемы с поиском нужных классов появятся во время выполнения ,источник
NoClassDefFoundError
обычно возникает, когда возникает проблема (исключение выдается) с инициализацией класса статическим блоком или статическими полями, поэтому класс не может быть успешно инициализированError
а другой -Exception
. :)ClassNotFoundException генерируется, когда сообщаемый класс не найден ClassLoader. Обычно это означает, что класс отсутствует в CLASSPATH. Это также может означать, что рассматриваемый класс пытается загрузиться из другого класса, который был загружен в родительский загрузчик классов, и, следовательно, класс из дочернего загрузчика классов не виден. Это иногда имеет место при работе в более сложных средах, таких как сервер приложений (WebSphere печально известен такими проблемами загрузчика классов).
Люди часто имеют тенденцию путать
java.lang.NoClassDefFoundError
с тем,java.lang.ClassNotFoundException
но есть важное различие. Например, исключение (ошибка действительно, такjava.lang.NoClassDefFoundError
как это подкласс java.lang.Error), напримерне означает, что класс ActiveMQConnectionFactory отсутствует в CLASSPATH. На самом деле это совсем наоборот. Это означает, что класс ActiveMQConnectionFactory был найден ClassLoader, однако при попытке загрузить класс возникла ошибка при чтении определения класса. Обычно это происходит, когда у рассматриваемого класса есть статические блоки или члены, которые используют класс, который не найден ClassLoader. Поэтому, чтобы найти виновника, просмотрите источник рассматриваемого класса (в данном случае ActiveMQConnectionFactory) и найдите код, используя статические блоки или статические члены. Если у вас нет доступа к источнику, просто декомпилируйте его, используя JAD.
Рассматривая код, скажем, вы нашли строку кода, как показано ниже, убедитесь, что класс SomeClass входит в ваш CLASSPATH.
Совет: Чтобы узнать, к какому jar принадлежит класс, вы можете использовать веб-сайт jarFinder. Это позволяет вам указать имя класса с помощью подстановочных знаков, и он ищет класс в своей базе данных jar. jarhoo позволяет вам делать то же самое, но его больше нельзя использовать.
Если вы хотите определить, к какому jar-классу принадлежит класс, в локальном пути, вы можете использовать утилиту, например jarscan ( http://www.inetfeedback.com/jarscan/ ). Вы просто указываете класс, который хотите найти, и путь к корневому каталогу, в котором вы хотите начать поиск класса в jar-файлах и zip-файлах.
источник
NoClassDefFoundError
это ошибка связи в принципе. Это происходит, когда вы пытаетесь создать экземпляр объекта (статически с «новым»), и не обнаруживается, когда это было во время компиляции.ClassNotFoundException
является более общим и является исключением во время выполнения, когда вы пытаетесь использовать класс, который не существует. Например, у вас есть параметр в функции, принимающий интерфейс, и кто-то передает класс, который реализует этот интерфейс, но у вас нет доступа к классу. Он также охватывает случай динамической загрузки класса, такой как использованиеloadClass()
илиClass.forName()
.источник
NoClassDefFoundError (NCDFE) происходит, когда ваш код выполняет «new Y ()» и не может найти класс Y.
Может просто случиться так, что Y отсутствует в загрузчике классов, как предлагают другие комментарии, но возможно, что класс Y не подписан или имеет недопустимую подпись, или что Y загружен другим загрузчиком классов, невидимым для вашего кода или даже то, что Y зависит от Z, который не может быть загружен по любой из вышеуказанных причин.
Если это произойдет, JVM запомнит результат загрузки X (NCDFE) и будет просто выдавать новый NCDFE каждый раз, когда вы запрашиваете Y, не сообщая вам, почему:
сохраните это как a.java где-нибудь
Код просто пытается дважды создать новый класс «b», кроме этого, в нем нет ошибок и он ничего не делает.
Скомпилируйте код с помощью
javac a.java
, затем запустите, вызвавjava -cp . a
- он должен просто распечатать две строки текста, и он должен работать без ошибок.Затем удалите файл «$ b.class» (или заполните его мусором, или скопируйте поверх него a.class), чтобы имитировать отсутствующий или поврежденный класс. Вот что происходит:
Первый вызов приводит к исключению ClassNotFoundException (генерируемому загрузчиком классов, когда он не может найти класс), которое должно быть заключено в непроверенную NoClassDefFoundError, так как код в вопросе (
new b()
) должен просто работать.Вторая попытка, конечно, тоже потерпит неудачу, но, как вы можете видеть, исключенное завершение больше не существует, потому что ClassLoader, похоже, запоминает неудачные загрузчики классов. Вы видите только NCDFE без какой-либо подсказки о том, что на самом деле произошло.
Поэтому, если вы когда-нибудь увидите NCDFE без основной причины, вам нужно посмотреть, сможете ли вы отследить, когда класс был загружен в первый раз, чтобы найти причину ошибки.
источник
-verbose
или какой-либо подобной опции в зависимости от конкретной JVM? Возможно-verbose:class
, может быть,-verbose:class:jni
если использовать JNI, но я не уверен в синтаксисе. Если это полезно, возможно, вы могли бы показать результаты.-verbose:class
ни-verbose:jni
дать никакого дополнительного вывода, относящегося к отсутствующему классу.-verbose:class:jni
это неправильно: нужно указать две отдельные опции:.-verbose:class -verbose:jni
)С http://www.javaroots.com/2013/02/classnotfoundexception-vs.html :
ClassNotFoundException
: происходит, когда загрузчик классов не может найти требуемый класс в пути к классам. Итак, в основном вы должны проверить путь к классу и добавить класс в путь к классам.NoClassDefFoundError
: это сложнее отладить и найти причину. Это генерируется, когда во время компиляции присутствуют требуемые классы, но во время выполнения классы изменяются или удаляются, или статическая инициализация класса выдает исключения. Это означает, что загружаемый класс присутствует в classpath, но один из классов, требуемых этим классом, либо удален, либо не удалось загрузить компилятором. Таким образом, вы должны увидеть классы, которые зависят от этого класса.Пример :
Теперь после компиляции обоих классов, если вы удалите файл Test1.class и запустите класс Test, он выдаст
ClassNotFoundException
: генерируется, когда приложение пытается загрузить класс через его имя, но не найдено определение для класса с указанным именем.NoClassDefFoundError
: брошено, если виртуальная машина Java пытается загрузить определение класса, и определение класса не найдено.источник
-verbose
или какой-либо подобной опции в зависимости от конкретной JVM? Возможно-verbose:class
, может быть,-verbose:class:jni
если использовать JNI, но я не уверен в синтаксисе.-verbose:class:jni
это неправильно, но вы можете передать два отдельных варианта:-verbose:class -verbose:jni
.Они тесно связаны. A
ClassNotFoundException
генерируется, когда Java отправляется на поиск определенного класса по имени и не может успешно его загрузить. ANoClassDefFoundError
выдается, когда Java ищет класс, который был связан с каким-то существующим кодом, но не может найти его по той или иной причине (например, неверный путь к классу, неправильная версия Java, неправильная версия библиотеки) и является полностью фатальным поскольку это указывает на то, что что-то пошло не так.Если у вас есть фон C, CNFE - это как сбой в
dlopen()
/,dlsym()
а NCDFE - проблема с компоновщиком; во втором случае соответствующие файлы классов никогда не должны были быть скомпилированы в конфигурации, которую вы пытаетесь использовать.источник
Пример № 1:
Если
com/example/Class1
не существует ни в одном из путей к классам, он выбрасываетClassNotFoundException
.Пример № 2:
Если
com/example/Class2
существовал во время компиляции B, но не найден во время выполнения, он выбрасываетNoClassDefFoundError
.Оба являются исключениями времени выполнения.
источник
ClassNotFoundException генерируется при попытке загрузить класс путем ссылки на него через строку. Например, параметр to в Class.forName () является строкой, и это повышает вероятность того, что недопустимые двоичные имена будут переданы загрузчику классов.
ClassNotFoundException генерируется, когда встречается потенциально недопустимое двоичное имя; например, если имя класса имеет символ '/', вы обязаны получить исключение ClassNotFoundException. Он также генерируется, когда класс с прямой ссылкой недоступен в пути к классам.
С другой стороны, выбрасывается NoClassDefFoundError
Короче говоря, NoClassDefFoundError обычно генерируется в операторах new () или вызовах методов, которые загружают ранее отсутствующий класс (в отличие от загрузки классов на основе строк для ClassNotFoundException), когда загрузчик классов не может найти или загрузить определение класса ( с).
В конечном счете, реализация ClassLoader создает экземпляр ClassNotFoundException, когда он не может загрузить класс. Большинство пользовательских реализаций загрузчика классов выполняют это, поскольку они расширяют URLClassLoader. Обычно загрузчики классов явно не генерируют NoClassDefFoundError ни в одной из реализаций метода - это исключение обычно генерируется из JVM в компиляторе HotSpot, а не самим загрузчиком классов.
источник
Разница между ClassNotFoundException и NoClassDefFoundError
источник
Исключение: исключения возникают во время выполнения программы. Программист может обработать это исключение, попробовав catch block. У нас есть два типа исключений. Проверено исключение, которое выдает во время компиляции. Исключения во время выполнения, которые генерируются во время выполнения, эти исключения обычно происходят из-за плохого программирования.
Ошибка: это вовсе не исключения, это выходит за рамки возможностей программиста. Эти ошибки обычно генерируются JVM.
источник изображения
Разница:
ClassNotFoundException:
ClassNotFoundException
.ClassNotFoundException
это проверенное исключение, полученное непосредственно изjava.lang.Exception
класса, и вам необходимо обеспечить явную обработку для негоClassNotFoundException
появляется, когда происходит явная загрузка класса путем предоставления имени класса во время выполнения с использованием ClassLoader.loadClass (), Class.forName () и ClassLoader.findSystemClass ().NoClassDefFoundError:
NoClassDefFoundError
.NoClassDefFoundError
Ошибка, полученная изLinkageError
класса, которая используется для указания случаев ошибки, когда класс зависит от какого-то другого класса и этот класс несовместимо изменился после компиляции.NoClassDefFoundError
является результатом неявной загрузки класса из-за вызова метода из этого класса или любой переменной доступа.сходства:
NoClassDefFoundError
и другоеClassNotFoundException
связано с недоступностью класса во время выполнения.ClassNotFoundException
иNoClassDefFoundError
связаны с Java classpath.источник
Учитывая действия sussystem загрузчика класса:
Эта статья очень помогла мне понять разницу: http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-5.html
Таким образом, ClassNotFoundException является основной причиной NoClassDefFoundError .
А NoClassDefFoundError - это особый случай ошибки загрузки типа, которая возникает на этапе связывания .
источник
Добавьте одну возможную причину на практике:
На практике ошибка может быть выброшена без вывода сообщений , например, вы отправляете задачу таймера, а в задаче таймера она выдает ошибку , в то время как в большинстве случаев ваша программа только перехватывает исключение . Затем основной цикл таймера заканчивается без какой-либо информации. Ошибка, аналогичная NoClassDefFoundError, - это ExceptionInInitializerError , когда ваш статический инициализатор или инициализатор для статической переменной выдает исключение.
источник
ClassNotFoundException - это проверенное исключение, которое возникает, когда мы сообщаем JVM загружать класс по его строковому имени, используя методы Class.forName () или ClassLoader.findSystemClass () или ClassLoader.loadClass (), и упомянутый класс не найден в classpath.
В большинстве случаев это исключение возникает при попытке запустить приложение без обновления пути к классу необходимыми файлами JAR. Например, вы, возможно, видели это исключение при выполнении кода JDBC для подключения к вашей базе данных, т.е. MySQL, но ваш путь к классам не имеет JAR для него.
Ошибка NoClassDefFoundError возникает, когда JVM пытается загрузить определенный класс, который является частью выполнения вашего кода (как часть обычного вызова метода или как часть создания экземпляра с использованием нового ключевого слова), и этот класс отсутствует в вашем пути к классам, но был присутствует во время компиляции, потому что для выполнения вашей программы вам нужно скомпилировать ее, и если вы пытаетесь использовать класс, которого нет, компилятор вызовет ошибку компиляции.
Ниже приводится краткое описание
Вы можете прочитать все о ClassNotFoundException против NoClassDefFoundError для более подробной информации.
источник
Я напоминаю себе следующее снова и снова, когда мне нужно обновить
ClassNotFoundException
Классовая иерархия
Во время отладки
NoClassDefFoundError
Классовая иерархия
Во время отладки
источник
ClassNotFoundException и NoClassDefFoundError происходят, когда определенный класс не найден во время выполнения. Однако они происходят в разных сценариях.
ClassNotFoundException - это исключение, которое возникает, когда вы пытаетесь загрузить класс во время выполнения с помощью методов Class.forName () или loadClass (), и упомянутые классы не найдены в пути к классам.
NoClassDefFoundError - это ошибка, которая возникает, когда определенный класс присутствует во время компиляции, но отсутствует во время выполнения.
Когда вы скомпилируете вышеуказанную программу, будут сгенерированы два файла .class. Один из них - A.class, а другой - B.class. Если вы удалите файл A.class и запустите файл B.class, Java Runtime System выдаст NoClassDefFoundError, как показано ниже:
источник