Я получаю NoClassDefFoundError когда я запускаю свое приложение Java. Что обычно является причиной этого?
Содержание
19 ответов:
Это возникает, когда есть файл класса, от которых зависит код, и он присутствует во время компиляции, но не во время выполнения. Ищите различия во времени сборки и пути к классам среды выполнения.
хотя возможно, что это связано с несоответствием пути к классам между временем компиляции и временем выполнения, это не обязательно верно.
важно держать два или три различных исключения прямо в нашей голове в этом случае:
java.lang.ClassNotFoundException это исключение указывает, что класс не найден в classpath. Это указывает на то, что мы пытались загрузить определение класса, А класс не существовал на экране. путь класса.
java.lang.NoClassDefFoundError это исключение указывает на то, что JVM искал в своей внутренней структуре данных определения класса определение класса и не нашел его. Это отличается от того, что он не может быть загружен из пути к классам. Обычно это указывает на то, что мы ранее пытались загрузить класс из пути к классу, но по какой-то причине это не удалось — Теперь мы пытаемся снова использовать класс (и, следовательно, его нужно загрузить, так как он не удался в прошлый раз), но мы даже не будем пытаться загрузить его, потому что мы не смогли загрузить его раньше (и разумно подозреваем, что мы снова потерпим неудачу). Более ранний сбой может быть ClassNotFoundException или ExceptionInInitializerError (указывающий на сбой в статическом блоке инициализации) или любое количество других проблем. Дело в том, что NoClassDefFoundError не обязательно является проблемой classpath.
вот код для иллюстрации java.lang.NoClassDefFoundError . Пожалуйста, смотрите Джаред!—5—> для подробного объяснения.
я обнаружил, что иногда я получаю ошибку NoClassDefFound, когда код компилируется с несовместимой версией класса, найденного во время выполнения. Конкретный экземпляр, который я помню, находится в библиотеке Apache axis. На самом деле было 2 версии на моем пути к классам во время выполнения, и он собирал устаревшую и несовместимую версию, а не правильную, вызывая ошибку NoClassDefFound. Это было в приложении командной строки, где я использовал команду, подобную этой.
я смог заставить его подобрать правильную версию с помощью:
NoClassDefFoundError В Java
определение:
виртуальная машина Java не может найти определенного класса во время выполнения, который был доступен во время компиляции.
Если класс присутствовал во время компиляции, но не доступен в Java classpath во время во время выполнения.

примеры:
- класс не находится в Classpath, нет уверенного способа узнать его, но много раз вы можете просто посмотреть, чтобы распечатать систему.getproperty ("java.classpath"), и он будет печатать classpath оттуда вы можете по крайней мере получить представление о вашем фактическом времени выполнения classpath.
простой пример NoClassDefFoundError-это класс, принадлежащий a отсутствующий файл JAR или JAR не был добавлен в classpath, или иногда имя jar было изменено кем-то, как в моем случае один из моих коллег изменил tibco.баночка в tibco_v3.jar и программа не работает с java.ленг.NoClassDefFoundError и мне было интересно, что случилось.
просто попробуйте запустить с явно-classpath вариант с classpath вы думаете, будет работать, и если он работает, то это верный короткий знак, что кто-то переопределяет java путь класса.
Возможные Решения:
- класс не доступен в Java Classpath.
- если вы работаете в среде J2EE, то видимость класса среди нескольких загрузчиков классов также может вызвать java.ленг.NoClassDefFoundError, см. примеры и раздел сценария для детального обсуждения.
- проверьте наличие java.ленг.ExceptionInInitializerError в файле журнала. NoClassDefFoundError из-за сбоя статической инициализации встречается довольно часто.
- потому что NoClassDefFoundError является подклассом Ява.ленг.LinkageError он также может прийти, если одна из его зависимостей, таких как собственная библиотека, может быть недоступна.
- любой сценарий запуска переопределяет переменную среды Classpath.
- вы можете запускать свою программу с помощью команды jar, А класс не был определен в атрибуте ClassPath файла манифеста.
Я получаю NoClassFoundError, когда классы, загруженные загрузчиком классов среды выполнения, не могут получить доступ к классам, уже загруженным загрузчиком Java. Поскольку разные загрузчики классов находятся в разных доменах безопасности (согласно java), jvm не позволит классам, уже загруженным rootloader, разрешаться в адресном пространстве загрузчика времени выполнения.
запустите программу с помощью ‘ java-javaagent: tracer.jar [YOUR java ARGS]’
он производит вывод, показывающий загруженный класс, и загрузчик env, который загрузил класс. Очень полезно проследить, почему класс не может быть разрешен.
Я был с помощью Spring Framework С Maven и решить эту ошибку в моем проекте.
в классе произошла ошибка выполнения. Я читал свойство как целое число, но когда он читал значение из файла свойств, его значение было двойным.
Spring не дал мне полную трассировку стека, на которой произошла ошибка выполнения. Он просто сказал NoClassDefFoundError . Но когда я выполнил его как родное приложение Java (взяв его из MVC), он дал ExceptionInInitializerError что было истинной причиной и как я проследил ошибку.
ответ@xli дал мне представление о том, что может быть неправильно в моем коде.
это лучшим решением Я нашел до сих пор.
Предположим, у нас есть пакет под названием org.mypackage содержащие классов:
- HelloWorld (основной класс)
- SupportClass
- UtilClass
и файлы, определяющие этот пакет, хранятся физически в каталоге D:myprogram (в Windows) или /home/user/myprogram (на Linux).
структура файла будет выглядеть этот: 
когда мы вызываем Java, мы указываем имя приложения для запуска: org.mypackage.HelloWorld . Однако мы также должны сказать Java, где искать файлы и каталоги, определяющие наш пакет. Поэтому для запуска программы мы должны использовать следующую команду: 
в случае, если вы сгенерировали-код (ЭДС и др.) может быть слишком много статических инициализаторов, которые потребляют все пространство стека.
техника ниже помогла мне много раз:
где TheNoDefFoundClass-это класс, который может быть "потерян" из-за предпочтения более старой версии той же библиотеки, используемой вашей программой. Это чаще всего происходит со случаями, когда клиентское программное обеспечение развертывается в доминирующий контейнер, вооруженный своими собственными загрузчиками классов и тоннами древних версий самых популярных библиотек.
Если кто-то приходит сюда из-за java.lang.NoClassDefFoundError: org/apache/log4j/Logger ошибка, в моем случае это было произведено, потому что я использовал log4j 2 (но я не добавил Все файлы, которые приходят с ним), и некоторые библиотеки зависимостей использовали log4j 1. Решение состояло в том, чтобы добавить Log4j 1.X мост: ЕАО log4j-1.2-api- .jar который поставляется с log4j 2. Дополнительная информация в log4j 2 миграция.
две разные контрольные копии одного и того же проекта
в моем случае проблема заключалась в неспособности Eclipse различать две разные копии одного и того же проекта. У меня есть один заблокированный на стволе (SVN version control), а другой работает в одной ветке за раз. Я попробовал одно изменение в рабочей копии как тестовый случай JUnit, который включал извлечение частного внутреннего класса, чтобы быть открытым классом самостоятельно, и пока он работал, я открываю другую копию проект, чтобы посмотреть на некоторые другие части кода, которые нуждаются в изменениях. В какой-то момент NoClassDefFoundError выскочил жалуясь, что частный внутренний класс не был там; двойной щелчок в трассировке стека привел меня к исходному файлу в неправильной копии проекта.
закрытие транковой копии проекта и запуск тестового случая снова избавились от проблемы.
Java не удалось найти класс A во время выполнения. Класс A был в Maven project ArtClient из другой рабочей области. Поэтому я импортировал ArtClient в свой проект Eclipse. Два моих проекта использовали ArtClient как зависимость. Я изменил ссылку на библиотеку на ссылку на проект для этих (путь сборки — > настроить путь сборки).
и проблема ушла.
У меня была та же проблема, и я был запас в течение многих часов.
Я нашел решение. В моем случае был статический метод, определенный из-за этого. JVM не может создать другой объект этого класса.
эта ошибка может быть вызвана бесконтрольно скачать требований.
в моем случае я смог устранить эту ошибку, при создании громкого проекта с открытым исходным кодом, переключившись с Java 9 на Java 8 с помощью SDKMAN!.
затем выполните чистую установку, как описано ниже.
при использовании Maven как ваш инструмент сборки, это иногда полезно — и обычно приятно, чтобы сделать очистить ‘install’ build тестирование инвалидов.
Теперь все был построен и установлен, вы можете пойти дальше и запустить тесты.
я исправил свою проблему, отключив preDexLibraries для всех модулей:
NoClassDefFoundError также может возникать, когда какой-либо ресурс недоступен во время выполнения, например файл свойств, который затронутый класс пытается загрузить из
Я получил это сообщение после удаления двух файлов из библиотеки SRC, и когда я вернул их, я продолжал видеть это сообщение об ошибке.
мое решение было: перезапустить Eclipse. С тех пор я больше не видел этого сообщения 🙂
убедитесь, что это соответствует в module:app и module:lib :
Содержание
Данная статья представляет перевод оригинальных публикаций следующих авторов:
Переводчик выражает благодарность Виктору Жуковскому за ценные правки и обсуждение рукописи.
Введение
Известно насколько неприятно видеть исключение java.lang.NoClassDefFoundError в потоке " main ". Многие разработчики проводят много времени прежде всего пытаясь понять, что пошло не так, какого класса не хватает и в чём суть проблемы. Во-первых, они путают между собой ClassNotfoundException и NoClassDefFoundError , хотя на самом деле это два совершенно разных исключения. Во-вторых, они используют метод «научного тыка» для решения проблемы NoClassDefFoundError вместо ясного понимания почему ошибка случилась и как её исправить. В этой статье по Java мы откроем некоторые секреты исправления ошибки NoClassDefFoundError в Java и поделимся своим опытом решения подобной проблемы.
Ошибка NoClassDefFoundError не является чем-то, что не может быть устранено или чем-то, что очень трудно устраняемо — нет, NoClassDefFoundError всего лишь проявление другой, более глубинной ошибки, что сбивает с толку большинство Java разработчиков. NoClassDefFoundError наиболее распространённая ошибка в Java разработке наряду с java.lang.OutOfMemoroyError: Java heap space и java.lang.OutOfMemoryError: PermGen space . Давайте посмотрим почему в Java происходит NoClassDefFoundError и что делать, чтобы её исправить.
В чём причина NoClassDefFoundError в Java?
NoClassDefFoundError в Java происходит тогда, когда виртуальная машина Java во время исполнения кода не может найти определённый класс, который был доступен во время компиляции. Например, если мы вызываем метод из класса или обращаемся к статическому члену класса и этот класс не доступен во время выполнения, то виртуальная машина Java выбрасывает NoClassDefFoundError . Важно понимать, что эта ошибка отличается от исключения ClassNotFoundException , которое происходит при попытке загрузки класса во время выполнения, причём важно, что имя этого класса было определено только во время выполнения, но не во время компиляции кода. Многие Java разработчики путают эти две ошибки и приходят в тупик при попытке разрешить вопрос.
Коротко говоря, NoClassDefFoundError происходит, если класс присутствовал во время компиляции, но не доступен в classpath во время исполнения. Обычно в этом случае вы увидите следующую строку в журнале ошибок:
Exception in thread "main" java.lang.NoClassDefFoundError
Фраза Exception in thread "main" означает, что именно поток " main " не может найти определённый класс. Вместо " main " может быть любой поток. Разница между тем, когда эта ошибка возникает в потоке " main " и в другом потоке в состоит том, что при возникновении в потоке " main " программа останавливается, а при возникновении в ином потоке, напротив, продолжает выполнение после ошибки.
Разница между java.lang.NoClassDefFoundError и ClassNotFoundException в Java
Прежде чем рассмотреть разницу между ClassNotFoundException и NoClassDefFoundError давайте рассмотрим, что между ними общего и что приводит к путанице между этими двумя ошибками:
- Обе ошибки связаны с недоступностью класса во время выполнения;
- Обе ошибки связаны с Java Classpath .
Теперь о различиях.
- ClassNotFoundException возникает в Java, если мы пытаемся загрузить класс во время выполнения используя методы Class.forName() , ClassLoader.loadClass() или ClassLoader.findSystemClass() , причём необходимый класс не доступен для Java. Зачастую причина тому — неправильный Classpath . В большинстве своём нам кажется, что мы используем корректный Classpath , но оказывается, что приложение использует совсем другой Classpath — не тот, который мы ожидали. Например, Classpath , заданный в манифесте jar файла, перезаписывает Classpath в переменной окружения CLASSPATH или опции -cp , заданной при запуске jar файла. В отличие от ClassNotFoundException в случае с NoClassDefFoundError проблемный класс присутствовал во время компиляции, и, поэтому, программа успешно прошла компиляцию, но по некоторой причине класс отсутствует во время исполнения. На мой взгляд решить NoClassDefFoundError легче чем ClassNotFoundException , поскольку вы точно знаете, что класс присутствовал во время сборки, но, в общем случае, это сильно зависит от среды разработки. Если вы работаете с J2EE окружением, вы можете получить NoClassDefFoundError даже если класс присутствует, поскольку он может быть невидимым для соответствующего загрузчика классов.
- ClassNotFoundException представляет собой проверяемое исключение, унаследованное непосредственно от класса java.lang.Exception , требующее явной обработки, в то время как NoClassDefFoundError это java.lang.Error , унаследованный от java.lang.LinkageError .
- ClassNotFoundException возникает в результате явной загрузки класса методами Class.forName() , ClassLoader.loadClass() или ClassLoader.findSystemClass() , в то время как NoClassDefFoundError — результат неявной загрузки класса, происходящей при попытке вызова метода из другого класса или доступа к его свойству.
NoClassDefFoundError в Java. Примеры и сценарии
Итак, очевидная причина NoClassDefFoundError состоит в том, что определённый класс не доступен в Classpath , так что нам нужно добавить его в Classpath или понять почему его нет в Classpath , хотя мы ожидаем его там найти. Для этого могут быть несколько причин:
- Класс не задан непосредственно в самой переменной Classpath .
- Распечатайте значение System.getproperty("java.classpath") в Java программе.
- Проверьте, не перезаписывает ли значение переменной окружения Classpath скрипт, запускающий приложение. Запустите программу с явной опцией -classpath , где укажите тот classpath , который по вашему мнению сработает, и если в этом случае программа заработает, то это хороший знак, что кто-то перезатирает ваш classpath .
- Класс отсутствует по местоположению, указанному в переменной Classpath .
- Проверьте, не удалил ли кто-то ваш jar-файл, или быть может переименовал его.
- Загрузчик классов не имеет прав на чтение файла, указанного в переменной Classpath , на уровне операционной системы.
- Используйте один и тот же >ClassPath файла манифеста, при запуске программы с помощью команды jar .
- Если вы используете файл сборки ANT для создания JAR архива и файла манифеста, то проверьте получает ли скрипт сборки ANT правильное значение classpath и добавляет ли его в файл manifest.mf .
- Виртуальная машина Java не нашла одну из зависимостей, например, нативную библиотеку. Эта ошибка выбрасывается поскольку NoClassDefFoundError является наследником java.lang.LinkageError .
- Храните ваши dll совместно с jar-файлами.
- Виртуальная машина Java не смогла завершить статическую инициализацию класса.
- Проверьте наличие ошибки java.lang.ExceptionInInitializerError в вашем журнале ошибок.
- Родительский загрузчик классов не видит класс, поскольку тот был уже загружен дочерним загрузчиком. Если вы работаете со средой J2EE, то неверная настройка видимости класса среди загрузчиков классов может также привести к java.lang.NoClassDefFoundError .
- Опечатка в XML конфигурации также может привести к NoClassDefFoundError в Java. Большинство программных платформ вроде Spring и Struts используют XML конфигурации для определения бинов. Случайно перепутав имя бина, вы можете получить java.lang.NoClassDefFoundError при загрузке другого класса, который зависит от бина. Это случается довольно часто в программных платформах Spring MVC и Apache Struts, где вы получаете тонны ошибок Exception in thread "main" java.lang.NoClassDefFoundError во время установки WAR или EAR файла.
- Переменные окружения или JDK установлены неверно.
- Проверьте переменные PATH и JAVA_HOME .
- Поставьте JDK другой версии.
Загрузчик классов в Java
Вкратце напомним, что загрузчик классов использует три основных принципа в своей работе: делегирование, видимость и уникальность.
- Делегирование означает, что каждый запрос на загрузку класса делегируется родительскому загрузчику классов.
- Видимость означает возможность найти классы загруженные загрузчиком классов: все дочерние загрузчики классов могут видеть классы, загруженные родительским загрузчиком, но родительский загрузчик не может видеть класс, загруженный дочерним.
- Уникальность гарантирует, что класс, загруженный родительским загрузчиком, не загружается повторно дочерним загрузчиком.
Каждый экземпляр загрузчика классов имеет связанный с ним родительский загрузчик классов. Предположим, загрузчик классов вашего приложения должен загрузить класс A . Первым делом загрузчик классов вашего приложения попытается делегировать поиск класса A своему родительскому загрузчику, прежде чем сам попытается его загрузить. Вы можете пройтись по длинной цепочке родительских загрузчиков пока не дойдёте до стартового загрузчика виртуальной машины Java.
Так в чём же тут проблема? Если класс A найден и загружен каким-нибудь родительским загрузчиком, это значит, что дочерний загрузчик загружать его уже не будет, а вы, возможно, именно этого и ждёте, что и приводит к NoClassDefFoundError .
Для лучшего понимания изобразим весь процесс загрузки в контексте платформы Java EE.
Как вы можете видеть при попытке загрузки класса дочерний загрузчик (Web App #1) делегирует загрузку родительскому загрузчику (Java EE App #1), который в свою очередь делегирует её системному стартовому загрузчику JVM. Если системный стартовый загрузчик не может загрузить класс, он возвращает управление родительскому загрузчику и так далее по цепочке пока класс не будет загружен каким-либо загрузчиком.
Рассмотрим простой пример, приводящий к NoClassDefFoundError из-за разной видимости классов между дочерним и родительским загрузчиками. Сделаем свой загрузчик MyClassLoader , наследник от java.lang.ClassLoader такой, чтобы он загружал классы с расширением .test вместо .class , находящиеся в пакете net.javacogito . Отметим, что стандартный загрузчик по умолчанию загружает данные только из файлов с расширением .class , так что загрузить Bar.test он не сможет. Схема дальнейшей работы такая:
- JVM загружает класс Bar из файла Bar.test .
- Класс Bar печатает свой загрузчик классов. Это MyClassLoader .
- JVM загружает класс Foo из файла Foo.class .
- Класс Foo печатает свой загрузчик классов. Это sun.misc.Launcher.AppClassLoader .
- Класс Foo вызывает статический метод printClassLoader() у класса Bar .
В этот момент JVM выдаёт NoClassDefFoundError , не смотря на то, что Bar был загружен ранее, поскольку родительский загрузчик AppClassLoader не видит классы, загруженные дочерним загрузчиком MyClassLoader .
Ниже на рисунке изображена схема делегирования загрузки, приводящая к NoClassDefFoundError .
При использовании данного кода:
Возникает ошибка NoClassDefFoundError :
run: Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/http/HttpEntity at com.github.sardine.SardineFactory.begin(SardineFactory.java:44) at com.github.sardine.SardineFactory.begin(SardineFactory.java:34) at javaapplication.JavaApplication.main(JavaApplication.java:25) Caused by: java.lang.ClassNotFoundException: org.apache.http.HttpEntity 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) . 3 more C:UsersLevchenkoAppDataLocalNetBeansCache8.2executor-snippets
un.xml:53: Java returned: 1
Подскажите, пожалуйста, почему возникает ошибка. Возможно, я подключил не все библиотеки которые нужны.
Добавил библиотеки. В структуре проекта теперь 3 библиотеки: sardine, httpclient, http core. Вот что получилось:





