Вопрос

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

Это было полезно?

Решение

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

Другие советы

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

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

<Ол>
  • java.lang.ClassNotFoundException Это исключение означает, что класс не найден в пути к классам. Это указывает на то, что мы пытались загрузить определение класса, а класс не существовал в пути к классам.

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

  • Вот код для иллюстрации 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;
    }
    

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

    set classpath=%classpath%;axis.jar
    

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

    set classpath=axis.jar;%classpath%;
    

    NoClassDefFoundError В Java

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

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

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

    enter image description here

    Примеры:

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

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

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

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

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

    Ресурсы:

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

    java.lang.Шаблоны проблем NoClassDefFoundError

    Это и есть тот самый лучшее решение Я нашел до сих пор.

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

    • HelloWorld (основной класс)
    • Класс поддержки
    • Класс утилиты

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

    Файловая структура будет выглядеть следующим образом:enter image description here

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

    Я использовал Spring Framework с Maven и решил эту ошибку в моем проекте.

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

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

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

    Я получаю 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 в МОДУЛЬНЫХ ТЕСТАХ...


    Один интересный случай, в котором вы могли бы увидеть много NoClassDefFoundErrors это когда ты:

    1. throw a RuntimeException в static блок вашего класса Example
    2. Перехватите его (или, если это просто не имеет значения, как будто оно брошено в тестовый пример)
    3. Попробуйте создать экземпляр этого класса 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.

    Если вы сгенерировали код (EMF и т. д.), может быть слишком много статических инициализаторов, которые занимают все пространство стека.

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

    Методика, приведенная ниже, помогла мне много раз:

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

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

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

    dexOptions {
            preDexLibraries false
            ...
    

    NoClassDefFoundError также может происходить, когда инициализатор статический пытается загрузить пакет ресурсов, который недоступен во время выполнения, например файл свойств, который уязвимый класс пытается загрузить из META-INF каталог, но <<>> # 8217; т там нет. Если вы не & # 8217; t ловите catch, иногда вы выигрываете & # 8217; t не сможете увидеть полную трассировку стека; чтобы преодолеть это, вы можете временно использовать предложение 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);
    }
    

    Если кто-то приходит сюда из-за ошибки 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 .

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

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

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

    <Ч>

    При использовании Maven в качестве инструмента для сборки иногда бывает полезно - и обычно приятно делать чистую «установку» сборки с отключенным тестированием .

    mvn clean install -DskipTests
    

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

    mvn test
    

    Я получил ошибки NoClassDefFound, когда не экспортировал класс в quot; Order and Export " вкладка в Путь сборки Java моего проекта. Обязательно поставьте галочку в & Quot; Заказ и экспорт & Quot; вкладка любых зависимостей, которые вы добавляете в путь сборки проекта. См. Предупреждение об затмении: XXXXXXXXXXX.jar будет не подлежит экспорту или публикации. Могут возникнуть исключения времени выполнения ClassNotFoundExceptions .

    Java не удалось найти класс A во время выполнения. Класс А был в Maven проекте ArtClient из другого рабочего пространства. Поэтому я импортировал ArtClient в свой проект Eclipse. Два моих проекта использовали ArtClient в качестве зависимости. Я изменил ссылку на библиотеку на ссылку на проект для этих (Build Path - & Gt; 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"
        }
    
    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top