Я получаю NoClassDefFoundError, когда запускаю свое Java-приложение. Что обычно является причиной этого?
Думали ли вы об изменении принятого ответа, чтобы тот, который сообщество считает более ценным, находился наверху?
Я считаю, что это также может произойти, если вы не запустите свою java-программу с правильным синтаксисом. Например, вы должны вызвать свой класс из корневой папки bin с полным именем пакета (например, my.package.myClass). Я был бы более конкретным, если бы мог, но я не особо разбираюсь в java. Я просто помню, как несколько раз облажался.




Это вызвано тем, что существует файл класса, от которого зависит ваш код, и он присутствует во время компиляции, но не обнаруживается во время выполнения. Ищите различия в пути к классам времени сборки и времени выполнения.
У меня возникла эта ошибка при помещении исходного файла в неправильное пространство имен / пакет. Я вычисленный мог просто положить его куда угодно, и компилятор был доволен. Оказывается, я должен был быть более прилежным, чтобы среда выполнения тоже была счастливой.
Однажды у меня была эта ошибка, когда моему серверу не хватило памяти во время загрузки файла. Каждый раз, когда я пытался загрузить, я получал другую ошибку. В конце концов он сказал мне, что у меня недостаточно места для кучи.
Этот ответ не обязательно верен и будет вводить в заблуждение многих людей! См. Лучший ответ Джареда ниже.
Я запустил mvn -X clean compiler package 2>&1 >test.log, чтобы увидеть кровавые подробности перед отчетом об ошибке NoClassDefFound.
@DaveL. Спасибо! Ответ Джареда с более чем 400 положительными голосами ниже! Один ответ с -4 голосами за (против?) Намного превосходит его. Есть что-то подозрительное в логике упорядочивания ответов SO.
Для кого-то это долгий путь, но я столкнулся с этой ошибкой, потому что рассматриваемый класс содержал SimpleDateFormat, который был инициализирован недопустимым символом (у меня был T в середине вместо «T»).
Как ни странно, я просто перекомпилировал свой файл, и это, похоже, прояснило ситуацию. Должно быть, я что-то изменил с момента первоначальной компиляции
Имя класса (NoClassDefFoundError) означает, что файл класса найден и загружен, но не может быть преобразован в определение класса JVM, он, возможно, нарушен любым неперехваченным исключением в статическом инициализаторе или помещен в другое место, отличное от того, которое подразумевает его пространство имен (подпуть в банке или папке, неправильный регистр имени файла).
Я обнаружил, что иногда я получаю ошибку NoClassDefFound, когда код компилируется с несовместимой версией класса, обнаруженной во время выполнения. Я помню конкретный экземпляр с библиотекой оси apache. На самом деле в моем пути к классам времени выполнения было 2 версии, и он собирал устаревшую и несовместимую версию, а не правильную, что вызывало ошибку NoClassDefFound. Это было в приложении командной строки, где я использовал команду, подобную этой.
set classpath=%classpath%;axis.jar
Я смог подобрать правильную версию, используя:
set classpath=axis.jar;%classpath%;
Была такая же проблема. Оказывается, я скомпилировал военный файл с помощью Java7, но моя установка Tomcat использовала Java6. Мне пришлось обновить свои переменные среды
Если это произойдет, я скажу, что Java в беспорядке. +2, если это правда. Пока не могу это проверить. Если найдено true, снова сделает +1 (в комментариях)
Хотя возможно, что это связано с несоответствием пути к классам во время компиляции и времени выполнения, это не обязательно так.
В этом случае важно держать в голове два-три разных исключения:
java.lang.ClassNotFoundException Это исключение указывает, что класс не был найден в пути к классам. Это указывает на то, что мы пытались загрузить определение класса, а класс не существует в пути к классам.
java.lang.NoClassDefFoundError Это исключение указывает, что JVM искала в своей внутренней структуре данных определения класса определение класса и не нашла его. Это отличается от того, чтобы сказать, что он не может быть загружен из пути к классам. Обычно это указывает на то, что мы ранее пытались загрузить класс из пути к классам, но по какой-то причине это не удалось - теперь мы пытаемся снова использовать класс (и, следовательно, нам нужно загрузить его, поскольку он не удался в прошлый раз), но мы ' re даже не будет пытаться загрузить его, потому что нам не удалось загрузить его ранее (и есть основания подозревать, что мы снова потерпим неудачу). Более ранняя ошибка могла быть ClassNotFoundException или ExceptionInInitializerError (указывающая на сбой в статическом блоке инициализации) или любое количество других проблем. Дело в том, что NoClassDefFoundError не обязательно является проблемой пути к классам.
Спасибо, что упомянули причину ошибки NoClassDefFoundError, это мне очень помогло! В моем случае раньше было выброшено исключение ExceptionInInitializerError, именно так я узнал об ошибках в статических блоках.
@Jared, когда я получаю Error: Could not find or load main class, он будет отнесен к какой категории ошибок?
@Pops: Язык стал более подробным, чтобы указать объекты глаголов "попробовать" :)
ClassCircularityError и ClassFormatError также могут возникать в процессе загрузки: docs.oracle.com/javase/specs/jls/se5.0/html/…
@Vikram «не удалось найти или загрузить основной класс» не является исключением Java, это вызвано программой запуска (которая проверяет JAR и основной атрибут манифеста).
У меня тоже возникает эта проблема, пытаясь запустить тест junit. как мне проверить путь к классам времени компиляции и времени выполнения?
Я запустил mvn -X clean compiler package 2>&1 >test.log, чтобы увидеть кровавые подробности перед отчетом об ошибке NoClassDefFound. Это действительно указывало на то, что это было вызвано предыдущим исключением ClassNotFound для класса, который, как я думал, я больше не использую.
ClassNotFoundException также возникает, когда класс имеет статическую инициализацию, которая вызывает ошибку или исключение. Наверное, им следовало выбрать для этого мероприятия другое название.
Может ли кто-нибудь помочь мне понять утверждение в этом ответе The earlier failure could be a ClassNotFoundException or an ExceptionInInitializerError (indicating a failure in the static initialization block). Может ли предыдущая возможная ошибка быть ClassNotFoundException, потому что предыдущая ошибка должна быть выдана при загрузке класса, как в статическом блоке. А статический блок не позволяет генерировать проверенное исключение.
@VipulGoyal: Я уже давно не использую Java в повседневной жизни. Насколько я помню, исключение ClassNotFoundException ВСЕГДА имеет другую основную причину при первом вызове данного вызова JVM, и эта основная причина включается в качестве причины исключения. Последующие попытки загрузить класс могут немедленно вызвать исключение ClassNotFoundException, если у JVM есть основания полагать, что ничего не изменилось, и он по-прежнему не загружается. Кто-то поправит меня, если память померкнет;)
Если я получаю NoClassDefFoundError, как может «предыдущая ошибка быть ClassNotFoundException»? Что это значит, когда я получаю только «NoClassDefFoundErrors»?
Вот код, иллюстрирующий java.lang.NoClassDefFoundError. Пожалуйста, см. Ответ Джареда для подробного объяснения.
NoClassDefFoundErrorDemo.java
public class NoClassDefFoundErrorDemo {
public static void main(String[] args) {
try {
// The following line would throw ExceptionInInitializerError
SimpleCalculator calculator1 = new SimpleCalculator();
} catch (Throwable t) {
System.out.println(t);
}
// The following line would cause NoClassDefFoundError
SimpleCalculator calculator2 = new SimpleCalculator();
}
}
SimpleCalculator.java
public class SimpleCalculator {
static int undefined = 1 / 0;
}
И причина в том, что после первой попытки jvm уже знает, что он не будет работать, и второй раз генерирует другое исключение?
@ikamen Видимо где-то хранилась неудачная инициализация класса SimpleCalculator после деления на ноль? Есть ли у кого-нибудь ссылка на официальную документацию по такому поведению?
@PhilipRego Не уверен, что вы имеете в виду под «чистым» NoClassDefFoundError. При первом вызове new SimpleCalculator() возникает исключение ExceptionInInitializerError, вызванное ArithmeticException. Во второй раз, когда вы вызываете new SimpleCalculator(), вы получаете NoClassDefFoundError, столь же чистый, как и любой другой. Дело в том, что вы можете получить NoClassDefFoundError по другой причине, кроме SimpleCalculator.class, который не находится в пути к классам во время выполнения.
Я использовал Spring Framework с Maven и решил эту ошибку в своем проекте.
В классе произошла ошибка времени выполнения. Я читал свойство как целое число, но когда он читал значение из файла свойств, его значение было двойным.
Spring не дал мне полной трассировки стека, на какой строке произошел сбой во время выполнения.
Он просто сказал NoClassDefFoundError. Но когда я выполнил его как собственное Java-приложение (взяв его из MVC), он дал ExceptionInInitializerError, который был истинной причиной, и именно так я отследил ошибку.
Ответ @ xli дал мне представление о том, что может быть не так в моем коде.
То же самое произошло со мной при программировании сервлета (NoClassDefFoundError был фактически вызван ExceptionInInitalizerError, который был вызван DateTimeParseException). Это немного вводит в заблуждение, не так ли? Я знаю, что у них, вероятно, были свои причины сделать это таким, но было бы так хорошо иметь хотя бы небольшой намек на то, что NoClassDefFoundError был результатом другого исключения, без необходимости его выводить. Было бы намного яснее просто бросить ExceptionInInitializerError снова. Иногда связь между ними может быть не такой очевидной.
Я получаю NoClassFoundError, когда классы, загруженные загрузчиком классов среды выполнения, не могут получить доступ к классам, уже загруженным корневым загрузчиком java. Поскольку разные загрузчики классов находятся в разных доменах безопасности (в соответствии с java), jvm не позволяет классам, уже загруженным корневым загрузчиком, разрешаться в адресном пространстве загрузчика времени выполнения.
Запустите вашу программу с помощью 'java -javaagent: tracer.jar [ВАШИ java ARGS]'
Он производит вывод, показывающий загруженный класс и env загрузчика, который загрузил класс. Это очень полезно для отслеживания того, почему класс не может быть разрешен.
// ClassLoaderTracer.java
// From: https://blogs.oracle.com/sundararajan/entry/tracing_class_loading_1_5
import java.lang.instrument.*;
import java.security.*;
// manifest.mf
// Premain-Class: ClassLoadTracer
// jar -cvfm tracer.jar manifest.mf ClassLoaderTracer.class
// java -javaagent:tracer.jar [...]
public class ClassLoadTracer
{
public static void premain(String agentArgs, Instrumentation inst)
{
final java.io.PrintStream out = System.out;
inst.addTransformer(new ClassFileTransformer() {
public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
String pd = (null == protectionDomain) ? "null" : protectionDomain.getCodeSource().toString();
out.println(className + " loaded by " + loader + " at " + new java.util.Date() + " in " + pd);
// dump stack trace of the thread loading class
Thread.dumpStack();
// we just want the original .class bytes to be loaded!
// we are not instrumenting it...
return null;
}
});
}
}
Ссылка мертва. Попробуйте архивную версию: web.archive.org/web/20131216000019/https://blogs.oracle.com/…
Это лучшее решение, который я нашел до сих пор.
Предположим, у нас есть пакет org.mypackage, содержащий классы:
а файлы, определяющие этот пакет, физически хранятся в каталоге D:\myprogram (в Windows) или /home/user/myprogram (в Linux).
Файловая структура будет выглядеть так:

Когда мы вызываем Java, мы указываем имя запускаемого приложения: org.mypackage.HelloWorld. Однако мы также должны указать Java, где искать файлы и каталоги, определяющие наш пакет. Итак, чтобы запустить программу, мы должны использовать следующую команду:

Я получил это сообщение после удаления двух файлов из библиотеки SRC, и когда я возвращал их, я продолжал видеть это сообщение об ошибке.
Мое решение было: перезапустить Eclipse. С тех пор я больше не видел это сообщение :-)
Это объясняется ответом, получившим наибольшее количество голосов: когда вы впервые скомпилировали файлы, затем вы удалили некоторые файлы, классы были удалены, поэтому во время выполнения вы получили ClassNotFound, затем вы вернули их обратно, но Eclipse не сделал этого. обратите внимание, что сгенерированные классы все еще отсутствовали, но после перезапуска Eclipse рабочая область была обновлена, и классы снова стали доступны, но в целом это не решение или обходной путь, решение заключается в том, чтобы найти, какой класс / jar отсутствует во время выполнения путь к классам.
Убедитесь, что это соответствует module:app и module:lib:
android {
compileSdkVersion 23
buildToolsVersion '22.0.1'
packagingOptions {
}
defaultConfig {
minSdkVersion 17
targetSdkVersion 23
versionCode 11
versionName "2.1"
}
Как ваше решение хоть как-то связано с этой общей проблемой?
Конфигурация образца не сбалансирована (три {s и два }). Ты можешь починить это?
У меня была такая же проблема, и я был в запасе много часов.
Я нашел решение. В моем случае из-за этого был определен статический метод. JVM не может создать другой объект этого класса.
Например,
private static HttpHost proxy = new HttpHost(proxyHost, Integer.valueOf(proxyPort), "http");
Приведенная ниже техника мне многократно помогала:
System.out.println(TheNoDefFoundClass.class.getProtectionDomain().getCodeSource().getLocation());
где TheNoDefFoundClass - это класс, который может быть «потерян» из-за предпочтения более старой версии той же библиотеки, используемой вашей программой. Чаще всего это происходит в тех случаях, когда клиентское программное обеспечение развертывается в доминирующем контейнере, вооруженном собственными загрузчиками классов и множеством древних версий самых популярных библиотек.
NoClassDefFoundError в Java
Определение:
Виртуальная машина Java не может найти определенный класс во время выполнения, который был доступен во время компиляции.
Если класс присутствовал во время компиляции, но не был доступен в пути к классам java во время выполнения.
Примеры:
Простой пример NoClassDefFoundError: класс принадлежит отсутствующему файлу JAR, или JAR не был добавлен в путь к классам, или иногда имя jar было изменено кем-то, как в моем случае один из моих коллег изменил tibco.jar на tibco_v3.jar, и программа сбой с java.lang.NoClassDefFoundError, и мне было интересно, что не так.
Просто попробуйте запустить с явным параметром -classpath путь к классам, который, по вашему мнению, будет работать, и если он работает, это верный короткий признак того, что кто-то переопределяет путь к классам Java.
Возможные решения:
Ресурсы:
3 способа решить проблему NoClassDefFoundError
java.lang.NoClassDefFoundError Шаблоны проблем
Отличный ответ. Думаю, я перепробовал все, что вы предлагаете, но проблема все еще не устранена. Я могу исключить некоторые из них из-за того, что jar работает с spring, но, похоже, не нравится java.sql (в моем случае драйвер sap db для Hana).
На самом деле это называется System.getproperty ("java.class.path")
Если у вас есть сгенерированный код (EMF и т. д.), Может быть слишком много статических инициализаторов, которые занимают все пространство стека.
См. Вопрос о переполнении стека Как увеличить размер стека Java?.
Неа. EMf как среда моделирования Eclipse. В автомобилестроении мы можем столкнуться с этой ошибкой при запуске сгенерированного кода.
Если кто-то приходит сюда из-за ошибки java.lang.NoClassDefFoundError: org/apache/log4j/Logger, в моем случае это было создано, потому что я использовал log4j 2 (но я не добавил все файлы, которые идут с ним), а некоторые библиотеки зависимостей использовали log4j 1. Решением было добавить Мост Log4j 1.x: jar log4j-1.2-api-<version>.jar, который поставляется с log4j 2. Дополнительная информация в log4j 2 миграция.
В моем случае проблема заключалась в неспособности Eclipse различать две разные копии одного и того же проекта. У меня один заблокирован на магистрали (контроль версий SVN), а другой работает в одной ветке за раз. Я опробовал одно изменение в рабочей копии в качестве тестового примера JUnit, который включал извлечение частного внутреннего класса в отдельный открытый класс, и пока он работал, я открываю другую копию проекта, чтобы посмотреть на другой часть кода, требующая изменений. В какой-то момент выскочил NoClassDefFoundError с жалобой на отсутствие частного внутреннего класса; двойной щелчок по трассировке стека привел меня к исходному файлу в неправильной копии проекта.
Закрытие основной копии проекта и повторный запуск тестового примера избавили от проблемы.
Java не смогла найти класс A во время выполнения. Класс A был в maven-проекте ArtClient из другого рабочего пространства. Итак, я импортировал ArtClient в свой проект Eclipse. Два моих проекта использовали ArtClient в качестве зависимости. Я изменил ссылку на библиотеку на ссылку на проект для этих (Путь сборки -> Настроить путь сборки).
И проблема ушла.
Я исправил свою проблему, отключив библиотеки preDexLibraries для всех модулей:
dexOptions {
preDexLibraries false
...
Эта ошибка может быть вызвана непроверенными требованиями Версия Java.
В моем случае мне удалось устранить эту ошибку при создании громкого проекта с открытым исходным кодом, переключившись с Java 9 на Java 8 с помощью SDKMAN!.
sdk list java
sdk install java 8u152-zulu
sdk use java 8u152-zulu
Затем выполните чистую установку, как описано ниже.
При использовании Maven в качестве инструмента сборки иногда полезно - и обычно приятно - выполнить сборку чистый 'install' с отключенным тестированием.
mvn clean install -DskipTests
Теперь, когда все собран и установлен, вы можете продолжить и запустить тесты.
mvn test
NoClassDefFoundError также может возникать, когда инициализатор статический пытается загрузить пакет ресурсов, который недоступен во время выполнения, например файл свойств, который затронутый класс пытается загрузить из каталога META-INF, но его там нет. Если вы не поймаете NoClassDefFoundError, иногда вы не сможете увидеть полную трассировку стека; чтобы преодолеть это, вы можете временно использовать предложение catch для Throwable:
try {
// Statement(s) that cause(s) the affected class to be loaded
} catch (Throwable t) {
Logger.getLogger("<logger-name>").info("Loading my class went wrong", t);
}
Это неверно. Отсутствие ресурс не даст вам этой ошибки. Вы получите его, только если учебный класс отсутствует.
@StephenC Может быть, мне стоит выделить эту часть больше, но я написал for example a properties file that the affected class tries to load from the META-INF directory. Это действительно произошло со мной, и я смог решить проблему NoClassDefFoundError, добавив отсутствующий файл свойств. Я добавил этот ответ именно потому, что при указанных обстоятельствах нельзя было ожидать такой ошибки.
Тогда вы пропустили что-то очень важное в своем объяснении, потому что единственный способ, которым отсутствующий файл ресурсов мог запускает это исключение, - это если вы пытаетесь загрузить файл ресурсов при инициализации static ... что вызвало непроверенное исключение и вызвало класс init потерпеть неудачу. Любое непроверенное исключение, распространяющееся из статической инициализации, сделает это.
Если я ошибаюсь (т.е. это не из-за неудачной инициализации static), мне было бы интересно увидеть реальный пример (т.е. MCVE), демонстрирующий поведение.
@StephenC Однако вы абсолютно правы :( Я просмотрел случай, когда я столкнулся с этой проблемой, и он действительно включал статический инициализатор, пытающийся загрузить пакет ресурсов. Я дополню / исправлю свое описание причины. Спасибо, что указали на это из.
Один интересный случай, когда вы можете увидеть много NoClassDefFoundErrors, - это когда вы:
throw a RuntimeException в блоке static вашего класса ExampleExamplestatic class Example {
static {
thisThrowsRuntimeException();
}
}
static class OuterClazz {
OuterClazz() {
try {
new Example();
} catch (Throwable ignored) { //simulating catching RuntimeException from static block
// DO NOT DO THIS IN PRODUCTION CODE, THIS IS JUST AN EXAMPLE in StackOverflow
}
new Example(); //this throws NoClassDefFoundError
}
}
NoClassDefError будет брошен вместе с ExceptionInInitializerError из статического блока RuntimeException.
Это особенно важный случай, когда вы видите NoClassDefFoundErrors в своем ИСПЫТАНИЯ УСТАНОВКИ.
В некотором смысле вы «разделяете» выполнение блока static между тестами, но исходный ExceptionInInitializerError будет только в одном тестовом примере. Первый, использующий проблемный класс Example. Другие тестовые примеры, в которых используется класс Example, просто вызовут NoClassDefFoundErrors.
Это чертовски полезный совет в реальной жизни. У меня была такая же ситуация с инициализаторами атрибутов класса. У вас есть только один шанс увидеть реальную проблему в журнале. Как только класс загружен (или все равно будет предпринята попытка), вам нужно все перезапустить.
У меня возникли ошибки NoClassDefFound, когда я не экспортировал класс на вкладке «Порядок и экспорт» в пути сборки Java моего проекта. Не забудьте поставить галочку на вкладке «Порядок и экспорт» для любых зависимостей, которые вы добавляете в путь сборки проекта. См. Предупреждение Eclipse: XXXXXXXXXXX.jar не будет экспортирован или опубликован. Runtime ClassNotFoundExceptions может привести к.
Это также может быть связано с тем, что вы копируете файл кода из среды IDE с определенным именем пакета и хотите попробовать запустить его с помощью терминала. Сначала вам нужно удалить имя пакета из кода. Со мной такое бывает.
У меня возникла эта ошибка, когда я добавил в свой проект зависимость Maven для другого модуля, проблема была наконец решена путем добавления -Xss2m в параметр JVM моей программы (по умолчанию это один мегабайт, начиная с JDK5.0). Считается, что у программы недостаточно стека для загрузки класса.
В моем случае я получал эту ошибку из-за несоответствия версий JDK. Когда я пытался запустить приложение из Intelij, оно не работало, но затем запуск из командной строки работал. Это связано с тем, что Intelij пытался запустить его с установленным Java 11 JDK, но в командной строке он работал с Java 8 JDK. После переключения этого параметра в меню «Файл»> «Структура проекта»> «Настройки проекта»> «SDK проекта» это сработало для меня.
Здесь все говорят о некоторых вещах конфигурации Java, проблемах JVM и т. д., В моем случае ошибка вообще не была связана с этими темами и имела очень тривиальную и легко решаемую причину: у меня была неправильная аннотация на моей конечной точке в моем контроллере ( Приложение Spring Boot).
У меня возникла интересная проблема с NoClassDefFoundError в JavaEE, работающем с сервером Liberty. Я использовал адаптеры ресурсов IMS, а в моем server.xml уже был адаптер ресурсов для imsudbJXA.rar. Когда я добавлял новый адаптер для imsudbXA.rar, я начинал получать эту ошибку для экземпляров объектов для DLIException, IMSConnectionSpec или SQLInteractionSpec. Я не мог понять, почему, но решил это, создав новый server.xml для моей работы, используя только imsudbXA.rar. Я уверен, что использование нескольких адаптеров ресурсов в server.xml - это нормально, у меня просто не было времени разбираться в этом.
Обновите [https://www.infoq.com/articles/single-file-execution-java11/]:
In Java SE 11, you get the option to launch a single source code file directly, without intermediate compilation. Just for your convenience, so that newbies like you don't have to run javac + java (of course, leaving them confused why that is).
У меня была эта ошибка, но я не мог найти решение на основе этой темы, но решил ее сам.
Для моей проблемы я компилировал этот код:
package valentines;
import java.math.BigInteger;
import java.util.ArrayList;
public class StudentSolver {
public static ArrayList<Boolean> solve(ArrayList<ArrayList<BigInteger>> problems) {
//DOING WORK HERE
}
public static void main(String[] args){
//TESTING SOLVE FUNCTION
}
}
Затем я компилировал этот код в структуру папок, которая была похожа на / ProjectName / valentines
Компиляция прошла нормально, но попытка выполнить: java StudentSolver
Я получал NoClassDefError.
Чтобы исправить это, я просто удалил: package valentines;.
Я не очень хорошо разбираюсь в java-пакетах и тому подобном, но так я исправил свою ошибку, извините, если на нее уже ответил кто-то другой, но я не мог интерпретировать ее для своей проблемы.
@BoltClock Нам нужен канонический вопрос, чтобы указать на многочисленные дубликаты. Почему этого не может быть?