Java.lang.NoClassDefFoundError: Не удалось инициализировать класс XXX
public class PropHolder {
public static Properties prop;
static {
//code for loading properties from file
}
}
// Referencing the class somewhere else:
Properties prop = PropHolder.prop;
class PropHolder
- мой собственный класс. Класс находится в том же файле JAR основного класса. Так что это не должно потому, что какой-либо JAR отсутствует в пути к классам.
Когда я смотрю в файл JAR на jar tf myjarfile
, я вижу там PropHolder.class
.
Btw: код работает нормально на моей локальной машине. Но работать не удалось, когда я развертываю его с помощью некоторого script на сервере Linux. Поэтому я думаю, что это не проблема кода.
Но почему-то. процесс развертывания очень трудно отслеживать.
В чем может быть проблема?
Ответы
Ответ 1
Лучше всего, здесь есть проблема:
static {
//code for loading properties from file
}
Казалось бы, возникло какое-то необработанное исключение, которое распространялось до фактического загрузчика классов, пытающегося загрузить класс. Нам понадобится трассировка стека, чтобы подтвердить это.
Либо это, либо это произошло при создании статической переменной PropHolder.prop
.
Ответ 2
Вы получаете java.lang.NoClassDefFoundError
, который НЕ означает, что ваш класс отсутствует (в этом случае вы получите java.lang.ClassNotFoundException
). ClassLoader столкнулся с ошибкой при чтении определения класса при попытке прочитать класс.
Поместите попытку/улов внутри своего статического инициализатора и посмотрите на исключение. Если вы читаете некоторые файлы там и отличается от своей локальной среды, это, скорее всего, причина проблемы (возможно, файл не может быть найден, никаких разрешений и т.д.).
Ответ 3
NoClassDefFoundError не дает большой информации о том, что пошло не так внутри статического блока. Хорошая практика всегда иметь такой блок внутри статического {...} кода инициализации:
static {
try {
... your init code here
} catch (Throwable t) {
LOG.error("Failure during static initialization", t);
throw t;
}
}
Ответ 4
У меня было то же исключение, вот как я решил проблему:
Предпосылки:
-
Класс Junit (и тест), который расширил другой класс.
-
ApplicationContext инициализируется с помощью spring, который инициализирует проект.
-
Контекст приложения был инициализирован в методе @Before
Решение:
Инициализировать контекст приложения из метода @BeforeClass, поскольку родительский класс также потребовал некоторые классы, которые были инициализированы из контекста приложения.
Надеюсь, это поможет.
Ответ 5
Как упоминалось выше, это может быть несколько вещей. В моем случае у меня была статически инициализированная переменная, которая полагалась на отсутствующую запись в моем файле свойств. Добавлена отсутствующая запись в файл свойств, и проблема была решена.
Ответ 6
У меня было то же исключение - но только во время работы в режиме отладки,
Вот как я решил проблему (через 3 дня):
в build.gradle у меня было:
"multiDexEnabled true" установлено в разделе defaultConfig.
defaultConfig {
applicationId "com.xxx.yyy"
minSdkVersion 15
targetSdkVersion 28
versionCode 5123
versionName "5123"
// Enabling multidex support.
multiDexEnabled true
}
но, видимо, этого было недостаточно.
но когда я изменился:
public class MyAppClass extends Application
в:
public class MyAppClass extends MultiDexApplication
это решило это.
надеюсь, это поможет кому-то
Ответ 7
Всего несколько дней назад я встретил тот же вопрос, что и ваш. Весь код хорошо работает на моей локальной машине, но получается ошибка (noclassdeffound & initialize).
Поэтому я отправляю свое решение, но я не знаю, почему, я просто выдвигаю возможность. Я надеюсь, что кто-то знает, это объяснит это. @John Vint
Во-первых, я покажу вам свою проблему. Мой код имеет статическую переменную и статический блок. Когда я впервые встретил эту проблему, я попробовал решение Джона Винта и попытался поймать исключение. Однако я ничего не поймал. Поэтому я подумал, что это потому, что статическая переменная (но теперь я знаю, что это одно и то же) и до сих пор ничего не нашел.
Итак, я пытаюсь найти разницу между машиной Linux и моим компьютером. Затем я обнаружил, что эта проблема возникает только тогда, когда несколько потоков выполняются в одном процессе (кстати, у Linux-машины есть двойные ядра и двойные процессы). Это означает, что если в одном процессе выполняются две задачи (оба используют код с статическим блоком или переменными), это происходит неправильно, но если они работают в разных процессах, то оба они в порядке.
На машине Linux я использую
mvn -U clean test -Dtest=path
для запуска задачи и потому, что моя статическая переменная заключается в том, чтобы запустить контейнер (или, возможно, вы инициализируете новый загрузчик классов), поэтому он останется до остановки jvm, а jvm остановится только тогда, когда все задачи в одном процессе прекратятся, Каждая задача запускает новый контейнер (или загрузчик классов), и это сбивает jvm. В результате происходит ошибка.
Итак, как его решить? Мое решение состоит в том, чтобы добавить новую команду в команду maven и сделать каждую задачу в том же контейнере.
-Dxxx.version=xxxxx #sorry can't post more
Возможно, вы уже решили эту проблему, но все же надеетесь, что это поможет другим, кто встречает ту же проблему.
Ответ 8
Если вы работаете над проектом Android, убедитесь, что вы не вызываете никаких статических методов на каких-либо Android-классах. Я использую только JUnit + Mockito, поэтому, возможно, некоторые другие фреймворки могут помочь вам избежать проблемы в целом, я не уверен.
Моя проблема вызывала Uri.parse(uriString)
как часть статического инициализатора для unit test. Класс Uri - это Android API, поэтому конструктор unit test не смог его найти. Я изменил это значение на null
, и все вернулось к нормальному.
Ответ 9
У меня были те же проблемы:java.lang.NoClassDefFoundError: Не удалось инициализировать класс com.xxx.HttpUtils
static {
//code for loading properties from file
}
это проблема среды. Это означает, что свойства в application.yml неверны или пусты!