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

Resharper был разработан JetBrains и является портом функциональность IntelliJ к C#

364
задан pants 24 September 2017 в 11:47
поделиться

6 ответов

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

Для ClassNotFoundException :

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

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

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

Для NoClassDefFoundError :

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

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

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

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

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

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

385
ответ дан 23 November 2019 в 00:09
поделиться

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

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

35
ответ дан 23 November 2019 в 00:09
поделиться

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

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

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

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

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

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

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

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

9
ответ дан 23 November 2019 в 00:09
поделиться

Необходимо закрыть FileStream и Reader, либо явно используя .Close (), либо с помощью оператора using:

using (FileStream fs = new FileStream(@"C:\website\TransList.xslt", System.IO.FileMode.Open))
   {
    xslt.Load(XmlReader.Create(fs));
    using (var reader = mydoc.CreateReader())
        {
         xslt.Transform(reader, null, sw);
        }
     }
-121--4648436-

Всякий раз, когда вы получаете/передаете данные из сети, помните, чтобы преобразовать в/из сети и порядок байтов хоста. Здесь следует использовать функции C htons , htonl и т.д. или эквиваленты на вашем языке.

Всякий раз, когда вы считываете многобайтовые значения (например, UTF-16 символов или 32 битовых ints) из файла, так как этот файл мог быть создан в системе с другой зависимостью. Если файл UTF 16 или 32, он, вероятно, имеет спецификацию (метку порядка байтов). В противном случае формат файла должен будет каким-либо образом указать endianness.

-121--3165642-

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

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

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

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

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

private static SomeClass foo = new SomeClass();

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

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

82
ответ дан 23 November 2019 в 00:09
поделиться

Ошибка 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 , затем запустите, вызвав 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$1.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 () ) должно работать.

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

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

29
ответ дан 23 November 2019 в 00:09
поделиться

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

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

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

15
ответ дан 23 November 2019 в 00:09
поделиться
Другие вопросы по тегам:

Похожие вопросы: