Почему я получаю NoClassDefFoundError в Java?


Я получаю NoClassDefFoundError когда я запускаю свое приложение Java. Что обычно является причиной этого?

19 412

19 ответов:

Это возникает, когда есть файл класса, от которых зависит код, и он присутствует во время компиляции, но не во время выполнения. Ищите различия во времени сборки и пути к классам среды выполнения.

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

важно держать два или три различных исключения прямо в нашей голове в этом случае:

  1. java.lang.ClassNotFoundException это исключение указывает, что класс не найден в classpath. Это указывает на то, что мы пытались загрузить определение класса, А класс не существовал на экране. путь класса.

  2. java.lang.NoClassDefFoundError это исключение указывает на то, что JVM искал в своей внутренней структуре данных определения класса определение класса и не нашел его. Это отличается от того, что он не может быть загружен из пути к классам. Обычно это указывает на то, что мы ранее пытались загрузить класс из пути к классу, но по какой-то причине это не удалось - Теперь мы пытаемся снова использовать класс (и, следовательно, его нужно загрузить, так как он не удался в прошлый раз), но мы даже не будем пытаться загрузить его, потому что мы не смогли загрузить его раньше (и разумно подозреваем, что мы снова потерпим неудачу). Более ранний сбой может быть ClassNotFoundException или ExceptionInInitializerError (указывающий на сбой в статическом блоке инициализации) или любое количество других проблем. Дело в том, что NoClassDefFoundError не обязательно является проблемой classpath.

вот код для иллюстрации java.lang.NoClassDefFoundError. Пожалуйста, смотрите Джаред!--5--> для подробного объяснения.

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;
}

я обнаружил, что иногда я получаю ошибку NoClassDefFound, когда код компилируется с несовместимой версией класса, найденного во время выполнения. Конкретный экземпляр, который я помню, находится в библиотеке Apache axis. На самом деле было 2 версии на моем пути к классам во время выполнения, и он собирал устаревшую и несовместимую версию, а не правильную, вызывая ошибку NoClassDefFound. Это было в приложении командной строки, где я использовал команду, подобную этой.

set classpath=%classpath%;axis.jar

я смог заставить его подобрать правильную версию с помощью:

set classpath=axis.jar;%classpath%;

NoClassDefFoundError В Java

определение:

  1. виртуальная машина Java не может найти определенного класса во время выполнения, который был доступен во время компиляции.

  2. Если класс присутствовал во время компиляции, но не доступен в Java classpath во время во время выполнения.

enter image description here

примеры:

  1. класс не находится в Classpath, нет уверенного способа узнать его, но много раз вы можете просто посмотреть, чтобы распечатать систему.getproperty ("java.classpath"), и он будет печатать classpath оттуда вы можете по крайней мере получить представление о вашем фактическом времени выполнения classpath.
  2. простой пример NoClassDefFoundError-это класс, принадлежащий a отсутствующий файл JAR или JAR не был добавлен в classpath, или иногда имя jar было изменено кем-то, как в моем случае один из моих коллег изменил tibco.баночка в tibco_v3.jar и программа не работает с java.ленг.NoClassDefFoundError и мне было интересно, что случилось.

  3. просто попробуйте запустить с явно-classpath вариант с classpath вы думаете, будет работать, и если он работает, то это верный короткий знак, что кто-то переопределяет java путь класса.

  4. проблема с разрешением на файл JAR также может вызвать NoClassDefFoundError в Java.
  5. опечатка в конфигурации XML также может вызвать NoClassDefFoundError в Java.
  6. когда ваш скомпилированный класс, который определен в пакете, не присутствует в том же пакете при загрузке, как в случае с JApplet, он будет бросать NoClassDefFoundError в Java.

Возможные Решения:

  1. класс не доступен в Java Classpath.
  2. если вы работаете в среде J2EE, то видимость класса среди нескольких загрузчиков классов также может вызвать java.ленг.NoClassDefFoundError, см. примеры и раздел сценария для детального обсуждения.
  3. проверьте наличие java.ленг.ExceptionInInitializerError в файле журнала. NoClassDefFoundError из-за сбоя статической инициализации встречается довольно часто.
  4. потому что NoClassDefFoundError является подклассом Ява.ленг.LinkageError он также может прийти, если одна из его зависимостей, таких как собственная библиотека, может быть недоступна.
  5. любой сценарий запуска переопределяет переменную среды Classpath.
  6. вы можете запускать свою программу с помощью команды jar, А класс не был определен в атрибуте ClassPath файла манифеста.

ресурсы:

3 способа решить NoClassDefFoundError

java.ленг.Проблема Ошибке Типа Noclassdeffounderror шаблоны

Я получаю NoClassFoundError, когда классы, загруженные загрузчиком классов среды выполнения, не могут получить доступ к классам, уже загруженным загрузчиком Java. Поскольку разные загрузчики классов находятся в разных доменах безопасности (согласно java), jvm не позволит классам, уже загруженным rootloader, разрешаться в адресном пространстве загрузчика времени выполнения.

запустите программу с помощью ' java-javaagent: tracer.jar [YOUR 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;
            }
        });
    }
}

Я был с помощью Spring Framework С Maven и решить эту ошибку в моем проекте.

в классе произошла ошибка выполнения. Я читал свойство как целое число, но когда он читал значение из файла свойств, его значение было двойным.

Spring не дал мне полную трассировку стека, на которой произошла ошибка выполнения. Он просто сказал NoClassDefFoundError. Но когда я выполнил его как родное приложение Java (взяв его из MVC), он дал ExceptionInInitializerError что было истинной причиной и как я проследил ошибку.

ответ@xli дал мне представление о том, что может быть неправильно в моем коде.

это лучшим решением Я нашел до сих пор.

Предположим, у нас есть пакет под названием org.mypackage содержащие классов:

  • HelloWorld (основной класс)
  • SupportClass
  • UtilClass

и файлы, определяющие этот пакет, хранятся физически в каталоге D:\myprogram (в Windows) или /home/user/myprogram (на Linux).

структура файла будет выглядеть этот: enter image description here

когда мы вызываем Java, мы указываем имя приложения для запуска: org.mypackage.HelloWorld. Однако мы также должны сказать Java, где искать файлы и каталоги, определяющие наш пакет. Поэтому для запуска программы мы должны использовать следующую команду: enter image description here

в случае, если вы сгенерировали-код (ЭДС и др.) может быть слишком много статических инициализаторов, которые потребляют все пространство стека.

см. вопрос переполнения стека как увеличить размер стека Java?.

техника ниже помогла мне много раз:

System.out.println(TheNoDefFoundClass.class.getProtectionDomain().getCodeSource().getLocation());

где TheNoDefFoundClass-это класс, который может быть "потерян" из-за предпочтения более старой версии той же библиотеки, используемой вашей программой. Это чаще всего происходит со случаями, когда клиентское программное обеспечение развертывается в доминирующий контейнер, вооруженный своими собственными загрузчиками классов и тоннами древних версий самых популярных библиотек.

Если кто-то приходит сюда из-за java.lang.NoClassDefFoundError: org/apache/log4j/Logger ошибка, в моем случае это было произведено, потому что я использовал log4j 2 (но я не добавил Все файлы, которые приходят с ним), и некоторые библиотеки зависимостей использовали log4j 1. Решение состояло в том, чтобы добавить Log4j 1.X мост: ЕАО log4j-1.2-api-<version>.jar который поставляется с log4j 2. Дополнительная информация в log4j 2 миграция.

две разные контрольные копии одного и того же проекта

в моем случае проблема заключалась в неспособности Eclipse различать две разные копии одного и того же проекта. У меня есть один заблокированный на стволе (SVN version control), а другой работает в одной ветке за раз. Я попробовал одно изменение в рабочей копии как тестовый случай JUnit, который включал извлечение частного внутреннего класса, чтобы быть открытым классом самостоятельно, и пока он работал, я открываю другую копию проект, чтобы посмотреть на некоторые другие части кода, которые нуждаются в изменениях. В какой-то момент NoClassDefFoundError выскочил жалуясь, что частный внутренний класс не был там; двойной щелчок в трассировке стека привел меня к исходному файлу в неправильной копии проекта.

закрытие транковой копии проекта и запуск тестового случая снова избавились от проблемы.

Java не удалось найти класс A во время выполнения. Класс A был в Maven project ArtClient из другой рабочей области. Поэтому я импортировал ArtClient в свой проект Eclipse. Два моих проекта использовали ArtClient как зависимость. Я изменил ссылку на библиотеку на ссылку на проект для этих (путь сборки - > настроить путь сборки).

и проблема ушла.

У меня была та же проблема, и я был запас в течение многих часов.

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

например,

private static HttpHost proxy = new HttpHost(proxyHost, Integer.valueOf(proxyPort), "http");

эта ошибка может быть вызвана бесконтрольно скачать требований.

в моем случае я смог устранить эту ошибку, при создании громкого проекта с открытым исходным кодом, переключившись с Java 9 на Java 8 с помощью SDKMAN!.

sdk list java
sdk install java 8u152-zulu
sdk use java 8u152-zulu

затем выполните чистую установку, как описано ниже.


при использовании Maven как ваш инструмент сборки, это иногда полезно - и обычно приятно, чтобы сделать очистить 'install' build тестирование инвалидов.

mvn clean install -DskipTests

Теперь все был построен и установлен, вы можете пойти дальше и запустить тесты.

mvn test

я исправил свою проблему, отключив preDexLibraries для всех модулей:

dexOptions {
        preDexLibraries false
        ...

NoClassDefFoundError также может возникать, когда какой-либо ресурс недоступен во время выполнения, например файл свойств, который затронутый класс пытается загрузить из

Я получил это сообщение после удаления двух файлов из библиотеки SRC, и когда я вернул их, я продолжал видеть это сообщение об ошибке.

мое решение было: перезапустить Eclipse. С тех пор я больше не видел этого сообщения :-)

убедитесь, что это соответствует в module:app и module:lib:

android {
    compileSdkVersion 23
    buildToolsVersion '22.0.1'
    packagingOptions {
    }

    defaultConfig {
        minSdkVersion 17
        targetSdkVersion 23
        versionCode 11
        versionName "2.1"
    }