java.lang.NoClassDefFoundError: Не удалось инициализировать класс XXX - PullRequest
144 голосов
/ 07 сентября 2011
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-файле основного класса.Так что этого не должно быть, потому что в classpath отсутствует какой-либо JAR.

Когда я просматриваю файл JAR с помощью jar tf myjarfile, я вижу PropHolder.class, указанный там.

Кстати:код работает нормально на моей локальной машине.Но не смог сработать, когда я развернул его с каким-то скриптом на сервере Linux.Поэтому я думаю, что это не проблема кода.Но по какой-то причине.процесс развертывания очень сложно отследить.

В чем может быть проблема?

Ответы [ 8 ]

178 голосов
/ 07 сентября 2011

Моя лучшая ставка в том, что здесь есть проблема:

static {
    //code for loading properties from file
}

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

Либо так, либо это произошло при создании PropHolder.prop статической переменной.

109 голосов
/ 07 сентября 2011

Вы получаете java.lang.NoClassDefFoundError, что НЕ означает, что ваш класс отсутствует (в этом случае вы получите java.lang.ClassNotFoundException).ClassLoader столкнулся с ошибкой при чтении определения класса при попытке чтения класса.

Поместите try / catch внутри статического инициализатора и посмотрите на исключение.Если вы читаете там какие-то файлы и они отличаются от вашей локальной среды, это, скорее всего, является причиной проблемы (возможно, файл не найден, нет разрешений и т. Д.).

30 голосов
/ 19 мая 2012

NoClassDefFoundError не дает большой подсказки о том, что пошло не так внутри статического блока. Рекомендуется всегда иметь такой блок внутри статического кода инициализации {...}:

static {
  try {

    ... your init code here

  } catch (Throwable t) {
    LOG.error("Failure during static initialization", t);
    throw t;
  }
}
3 голосов
/ 17 июля 2014

У меня было то же исключение, вот как я решил проблему:

Условия:

  1. Класс Junit (и тест), который расширил другой класс.

  2. ApplicationContext инициализируется с помощью Spring, который инициирует проект.

  3. Контекст приложения был инициализирован в методе @Before

Решение:

Инициируйте контекст приложения из метода @BeforeClass, поскольку родительскому классу также требуются некоторые классы, которые были инициализированы из контекста приложения.

Надеюсь, это поможет.

1 голос
/ 31 октября 2018

У меня было то же исключение - но только во время работы в режиме отладки, Вот как я решил проблему (через 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 

это решило это. надеюсь, это кому-нибудь поможет

1 голос
/ 17 декабря 2014

Как уже упоминалось выше, это может быть несколько вещей.В моем случае у меня была статически инициализированная переменная, которая опиралась на отсутствующую запись в моем файле свойств.Добавил отсутствующую запись в файл свойств, и проблема была решена.

0 голосов
/ 13 декабря 2016

Если вы работаете над проектом Android, убедитесь, что вы не вызываете статические методы ни для каких классов Android.Я использую только JUnit + Mockito, так что, возможно, некоторые другие фреймворки могут помочь вам вообще избежать этой проблемы, я не уверен.

Моя проблема заключалась в вызове Uri.parse(uriString) как части статического инициализатора для модулятестовое задание.Класс Uri - это Android API, поэтому сборка тестового модуля не смогла его найти.Вместо этого я изменил это значение на null и все вернулось к норме.

0 голосов
/ 28 октября 2015

Всего несколько дней назад я встретил такой же вопрос, как и ваш.Весь код хорошо работает на моей локальной машине, но получается ошибка (noclassdeffound & initialize).Поэтому я публикую свое решение, но я не знаю почему, я просто выдвигаю возможность.Я надеюсь, что кто-то знает, это объяснит. @ Джон Винт Во-первых, я покажу вам мою проблему.Мой код имеет статическую переменную и статический блок оба.Когда я впервые столкнулся с этой проблемой, я попробовал решение Джона Винта и попытался поймать исключение.Однако я ничего не поймал.Поэтому я подумал, что это потому, что статические переменные (но теперь я знаю, что это одно и то же) и до сих пор ничего не нашли.Итак, я пытаюсь найти разницу между машиной Linux и моим компьютером.Затем я обнаружил, что эта проблема возникает только тогда, когда несколько потоков выполняются в одном процессе (кстати, на машине linux есть два ядра и два процесса).Это означает, что если в одном и том же процессе выполняются две задачи (обе используют код со статическим блоком или переменными), это не так, но если они выполняются в разных процессах, обе они в порядке.В машине Linux я использую

mvn -U clean  test -Dtest=path 

для запуска задачи, и потому что моя статическая переменная должна запускать контейнер (или, может быть, вы инициализируете новый загрузчик классов), поэтому он будет оставаться до остановки jvm,и jvm останавливается только тогда, когда все задачи в одном процессе останавливаются.Каждая задача запускает новый контейнер (или загрузчик классов), и это делает jvm запутанным.В результате происходит ошибка.Итак, как это решить?Мое решение состоит в том, чтобы добавить новую команду в команду maven и перевести все задачи в один и тот же контейнер.

-Dxxx.version=xxxxx #sorry can't post more

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

...