Я получаю, NoClassDefFoundError
когда я запускаю свое Java-приложение. Что обычно является причиной этого?
Я получаю, NoClassDefFoundError
когда я запускаю свое Java-приложение. Что обычно является причиной этого?
Ответы:
Это вызвано тем, что существует файл класса, от которого зависит ваш код, и он присутствует во время компиляции, но не найден во время выполнения. Ищите различия во времени сборки и во время выполнения классов.
Хотя возможно, что это связано с несоответствием пути к классам между временем компиляции и временем выполнения, это не всегда так.
В этом случае важно держать два или три разных исключения в нашей голове:
java.lang.ClassNotFoundException
Это исключение указывает, что класс не был найден в пути к классам. Это указывает на то, что мы пытались загрузить определение класса, а класс не существовал в пути к классам.
java.lang.NoClassDefFoundError
Это исключение указывает на то, что JVM искала в своей внутренней структуре данных определения класса определение класса и не нашла его. Это отличается от того, что он не может быть загружен из пути к классам. Обычно это указывает на то, что мы ранее пытались загрузить класс из пути к классам, но по какой-то причине это не удалось - теперь мы пытаемся использовать класс снова (и, следовательно, нужно загрузить его, так как в прошлый раз он не удался), но мы ' мы даже не собираемся пытаться загрузить его, потому что мы не смогли загрузить его раньше (и разумно подозреваем, что у нас снова получится ошибка). Более ранний сбой мог быть ClassNotFoundException или ExceptionInInitializerError (указывающий на сбой в блоке статической инициализации) или любым другим количеством проблем. Дело в том, что NoClassDefFoundError не обязательно является проблемой пути к классам.
Error: Could not find or load main class
это будет классифицировано под какой категорией ошибок?
Вот код для иллюстрации 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;
}
SimpleCalculator
после деления на ноль? У кого-нибудь есть ссылка на официальную документацию по этому поведению?
new SimpleCalculator()
вызове вы получаете ExceptionInInitializerError с вызванной ArithmeticException. Во второй раз вы вызываете new SimpleCalculator()
NoClassDefFoundError так же чисто, как и любой другой. Дело в том, что вы можете получить NoClassDefFoundError по причине, отличной от SimpleCalculator.class, отсутствующей в пути к классам во время выполнения.
NoClassDefFoundError в Java
Определение:
Виртуальная машина Java не может найти определенный класс во время выполнения, который был доступен во время компиляции.
Если класс присутствовал во время компиляции, но не был доступен в java classpath во время выполнения.
Примеры:
Простой пример NoClassDefFoundError - класс принадлежит отсутствующему файлу JAR или JAR не был добавлен в classpath, или иногда имя jar было изменено кем-то, как в моем случае один из моих коллег изменил tibco.jar на tibco_v3.jar, и программа не удалось с java.lang.NoClassDefFoundError, и мне было интересно, что не так.
Просто попробуйте запустить с явным параметром -classpath с classpath, который, по вашему мнению, будет работать, и если он работает, это верный короткий признак того, что кто-то переопределяет java classpath.
Возможные решения:
Ресурсы:
Я обнаружил, что иногда я получаю ошибку NoClassDefFound, когда код компилируется с несовместимой версией класса, найденной во время выполнения. Конкретный экземпляр, который я помню, связан с библиотекой оси Apache. На моем пути к классам во время выполнения было фактически две версии, и он выбирал устаревшую и несовместимую версию, а не правильную, вызывая ошибку NoClassDefFound. Это было в приложении командной строки, где я использовал команду, подобную этой.
set classpath=%classpath%;axis.jar
Я смог заставить его подобрать правильную версию, используя:
set classpath=axis.jar;%classpath%;
Это лучшее решение я нашел до сих пор.
Предположим, у нас есть пакет, org.mypackage
содержащий классы:
и файлы, определяющие этот пакет, хранятся физически в каталоге D:\myprogram
(в Windows) или/home/user/myprogram
(в Linux).
Структура файла будет выглядеть так:
Когда мы вызываем Java, мы указываем имя приложения для запуска: org.mypackage.HelloWorld
. Однако мы также должны указать Java, где искать файлы и каталоги, определяющие наш пакет. Итак, чтобы запустить программу, мы должны использовать следующую команду:
Я использовал 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;
}
});
}
}
Один интересный случай, в котором вы можете увидеть много случаев NoClassDefFoundErrors
, когда вы:
throw
RuntimeException
в static
блоке вашего классаExample
Example
static 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
.
Методика ниже помогла мне много раз:
System.out.println(TheNoDefFoundClass.class.getProtectionDomain().getCodeSource().getLocation());
где TheNoDefFoundClass - это класс, который может быть «потерян» из-за предпочтения более старой версии той же библиотеки, что и ваша программа. Чаще всего это происходит в тех случаях, когда клиентское программное обеспечение развертывается в доминирующем контейнере, оснащенном собственными загрузчиками классов и множеством древних версий наиболее популярных библиотек.
В случае, если вы сгенерировали код (EMF и т. Д.), Может быть слишком много статических инициализаторов, которые занимают все пространство стека.
См. Вопрос переполнения стека. Как увеличить размер стека Java? ,
NoClassDefFoundError
Это также может произойти, когда статический инициализатор пытается загрузить пакет ресурсов, который недоступен во время выполнения, например файл свойств, который уязвимый класс пытается загрузить из META-INF
каталога, но его там нет. Если вы не поймаете NoClassDefFoundError
, иногда вы не сможете увидеть полную трассировку стека; Чтобы преодолеть это, вы можете временно использовать catch
пункт для Throwable
:
try {
// Statement(s) that cause the affected class to be loaded
} catch (Throwable t) {
Logger.getLogger("<logger-name>").info("Loading my class went wrong", t);
}
for example a properties file that the affected class tries to load from the META-INF directory
. Это на самом деле произошло со мной, и я смог решить NoClassDefFoundError
, добавив отсутствующий файл свойств. Я добавил этот ответ именно потому, что никто не ожидал этой ошибки при указанных обстоятельствах.
static
инициализации ... который вызвал непроверенное исключение и вызвал класс init терпеть неудачу. Любое непроверенное исключение, распространяющееся из статической инициализации, сделает это.
static
инициализации), мне было бы интересно увидеть реальный пример (т.е. MCVE), который демонстрирует поведение.
Я получил эту ошибку, когда я добавил Maven-зависимость другого модуля в свой проект, и проблема была окончательно решена путем добавления -Xss2m
опции JVM в моей программе (по умолчанию это один мегабайт, начиная с JDK5.0). Считается, что программе не хватает стека для загрузки класса.
Если кто-то приходит сюда из-за java.lang.NoClassDefFoundError: org/apache/log4j/Logger
ошибки, в моем случае она возникла потому, что я использовал log4j 2 (но я не добавил все файлы, которые идут с ним), а некоторая библиотека зависимостей использовала log4j 1. Решением было добавить Log4j. 1.x bridge: jar, log4j-1.2-api-<version>.jar
который поставляется с log4j 2. Больше информации в log4j 2 миграции .
В моем случае проблема заключалась в неспособности Eclipse различать две разные копии одного и того же проекта. У меня один заблокирован на транке (контроль версий SVN), а другой работает в одной ветви одновременно. Я опробовал одно изменение в рабочей копии как тестовый пример JUnit, который включал в себя извлечение частного внутреннего класса в открытый класс, и пока он работал, я открываю другую копию проекта, чтобы посмотреть на некоторые другие часть кода, которая нуждалась в изменениях. В какой-то моментNoClassDefFoundError
всплыли жалобы на то, что частного внутреннего класса там не было; двойной щелчок в трассировке стека привел меня к исходному файлу в неправильной копии проекта.
Закрытие транковой копии проекта и запуск тестового примера снова избавили от проблемы.
Эта ошибка может быть вызвана непроверенными требованиями к версии 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
Я получил ошибки NoClassDefFound, когда не экспортировал класс на вкладке «Порядок и экспорт» в пути сборки Java моего проекта. Обязательно поставьте галочку на вкладке «Порядок и экспорт» всех зависимостей, которые вы добавляете в путь сборки проекта. См. Предупреждение Eclipse: XXXXXXXXXXX.jar не будет экспортирован или опубликован. Runtime ClassNotFoundExceptions может привести .
В моем случае я получал эту ошибку из-за несоответствия версий JDK. Когда я пытался запустить приложение из Intelij, оно не работало, но потом работало его из командной строки. Это связано с тем, что Intelij пытался запустить его с установленным Java 11 JDK, но в командной строке он работал с Java 8 JDK. После переключения этого параметра в меню «Файл»> «Структура проекта»> «Параметры проекта»> «Project SDK» он сработал.
Все говорят здесь о некоторой конфигурации Java, проблемах JVM и т. Д., В моем случае ошибка вообще не была связана с этими темами и имела очень тривиальную и легко решаемую причину: у меня была неправильная аннотация на моей конечной точке в контроллере ( Приложение Spring Boot).
У меня была интересная проблема с NoClassDefFoundError в JavaEE при работе с сервером Liberty. Я использовал адаптеры ресурсов IMS, и в моем server.xml уже был адаптер ресурсов для imsudbJXA.rar. Когда я добавил новый адаптер для imsudbXA.rar, я начал получать эту ошибку для объектов экземпляра для DLIException, IMSConnectionSpec или SQLInteractionSpec. Я не мог понять, почему, но я решил это, создав новый файл server.xml для своей работы, используя только imsudbXA.rar. Я уверен, что использование нескольких ресурсных адаптеров в server.xml - это нормально, у меня просто не было времени на это разбираться.
Java не смог найти класс A во время выполнения. Класс А был в Maven проекте ArtClient из другого рабочего пространства. Поэтому я импортировал ArtClient в свой проект Eclipse. Два моих проекта использовали ArtClient в качестве зависимости. Я изменил ссылку на библиотеку на ссылку проекта для этих (Build Path -> Configure Build Path).
И проблема ушла.
У меня была такая же проблема, и я был на складе в течение многих часов.
Я нашел решение. В моем случае был определен статический метод. JVM не может создать другой объект этого класса.
Например,
private static HttpHost proxy = new HttpHost(proxyHost, Integer.valueOf(proxyPort), "http");
Я получил это сообщение после удаления двух файлов из библиотеки SRC, и когда я возвращал их, я продолжал видеть это сообщение об ошибке.
Мое решение было: перезапустите Eclipse. С тех пор я больше не видел это сообщение :-)
Убедитесь, что это соответствует в module:app
и module:lib
:
android {
compileSdkVersion 23
buildToolsVersion '22.0.1'
packagingOptions {
}
defaultConfig {
minSdkVersion 17
targetSdkVersion 23
versionCode 11
versionName "2.1"
}
{s
и два }
). Ты можешь починить это?