Как решить java.lang.NoClassDefFoundError?


221

Я попробовал оба примера в Oracle Java Tutorials . Они оба компилируются нормально, но во время выполнения, оба появляются с этой ошибкой:

Exception in thread "main" java.lang.NoClassDefFoundError: graphics/shapes/Square
    at Main.main(Main.java:7)
Caused by: java.lang.ClassNotFoundException: graphics.shapes.Square
    at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    ... 1 more

Я думаю, что у меня может быть Main.javaфайл в неправильной папке. Вот иерархия каталогов:

graphics
 Main.java
 shapes
|    Square.java
|    Triangle.java
 linepoint
|    Line.java
|    Point.java
 spaceobjects
|    Cube.java
|    RectPrism.java

И вот Main.java:

import graphics.shapes.*;
import graphics.linepoint.*
import graphics.spaceobjects.*;

public class Main {
    public static void main(String args[]) {
        Square s = new Square(2,3,15);
        Line l = new Line(1,5,2,3);
        Cube c = new Cube(13,32,22);
    }
}

Что я здесь не так делаю?

ОБНОВИТЬ

После того, как я поместил Mainкласс в graphicsпакет (я добавил package graphics;к нему), установил для classpath значение «_test» (папка с графикой), скомпилировал его и запустил с помощью java graphics.Main(из командной строки), все заработало.

Действительно поздно ОБНОВЛЕНИЕ № 2

Я не использовал Eclipse (только Notepad ++ и JDK), и вышеприведенное обновление решило мою проблему. Тем не менее, кажется, что многие из этих ответов предназначены для Eclipse и IntelliJ, но имеют схожие концепции.


1
Глядя на ваш основной класс, он не в пакете (вы бы package graphics;наверху). Является ли graphicsглава вашей структуры пакета? Квадрат имеет package graphics.shapesнаверху?
владелец

1
Вы перечисляете, где находятся файлы .java, но так как то, что вы получаете, является проблемой во время выполнения , то, что вас действительно интересует, так это то, где находятся файлы .class и находятся ли они на вашем пути к классам или нет. Как вы выполняете основной класс?
Thor84no

Просто нажмите Shift + Ctrl + O в затмении, чтобы организовать свой импорт
happybuddha

Убедитесь, что вы правильно ввели имя класса. Я получал эту ошибку, потому что я не начинал имя класса с заглавной буквы
Джереми Борг

Это иногда происходит в IntelliJ IDEA после серьезного рефакторинга. Щелкните правой кнопкой мыши по вашему проекту и выберите -> Compile Module , а затем перезапустите проект, и он должен снова заработать.
Зар

Ответы:


223

После того, как вы скомпилируете свой код, вы получите .classфайлы для каждого класса в вашей программе. Эти двоичные файлы являются байт-кодом, который Java интерпретирует для выполнения вашей программы. NoClassDefFoundErrorПоказывает , что загрузчик классов (в данном случае java.net.URLClassLoader), который отвечает за классы динамически загрузки, не может найти.class файл класса , который вы пытаетесь использовать.

Ваш код не будет компилироваться, если требуемые классы отсутствуют (если классы не загружены с отражением), поэтому обычно это исключение означает, что ваш путь к классам не включает требуемые классы. Помните, что загрузчик классов (в частности java.net.URLClassLoader) будет искать классы в пакете abc в папке a / b / c / в каждой записи в вашем пути к классам. NoClassDefFoundErrorтакже может указывать, что у вас отсутствует транзитивная зависимость файла .jar, с которым вы скомпилировали и пытаетесь использовать.

Например, если у вас есть класс com.example.Foo, после компиляции у вас будет файл класса Foo.class. Скажем, например, ваш рабочий каталог .../project/. Этот файл класса должен быть размещен .../project/com/example, и вы должны установить свой путь к классу .../project/.

Примечание: я бы порекомендовал воспользоваться удивительными инструментами, которые существуют для языков Java и JVM. Современные IDE, такие как Eclipse и IDEA, и инструменты управления сборкой, такие как Maven или Gradle, помогут вам не беспокоиться о путях к классам (а также о них) и сосредоточиться на коде! Тем не менее, эта ссылка объясняет, как установить путь к классу при выполнении в командной строке.


Я читаю это из-за ошибки, с которой я столкнулся при попытке запустить модульный тест на Android. Оказывается, что NoClassDefFoundError, в моем случае, произошел в результате отсутствия зависимостей в тесте. Мне нужно подумать о внедрении зависимости, чтобы предотвратить подобные ошибки. Спасибо за подробный ответ.
типичный Дэнни

130

Я хотел бы исправить точку зрения других на NoClassDefFoundError.

NoClassDefFoundError может произойти по нескольким причинам, таким как

  1. ClassNotFoundException - .class не найден для этого ссылочного класса, независимо от того, доступен ли он во время компиляции или нет (т. Е. Базовый / дочерний класс).
  2. Файл класса расположен, но исключение поднялось при инициализации статических переменных
  3. Обнаружен файл класса. Возникла исключительная ситуация при инициализации статических блоков.

В первоначальном вопросе это был первый случай, который можно исправить, установив CLASSPATH в файл jar ссылочных классов или в его папку пакета.

Что значит сказать «доступно во время компиляции»?

  • Указанный класс используется в коде.
    Например: два класса, A и B (расширяет A). Если B ссылается непосредственно на код, он доступен во время компиляции, то есть A a = new B ();

Что значит сказать «недоступно во время компиляции»?

  • Класс времени компиляции и класс времени выполнения различаются, т.е., например, базовый класс загружается с использованием имени класса дочернего класса, например Class.forName ("имя класса")
    Например: два класса, A и B (расширяет A). Код имеет
    A a = Class.forName ("B"). NewInstance ();

В моем случае я скомпилировал класс, а они переместили его в каталог с именем app. Мне пришлось добавить строку package app;и перекомпилировать, прежде чем я смог переместить ее в приложение подкаталога.
Тако

1
Помимо перечисленных выше 3, ClassLoaders также может вызывать такую ​​ошибку, которая в основном является ClassNotFoundException, в этом сценарии класс может присутствовать в classpath, но пытаться загрузить из другого ClassLoader
Fahad

2 и 3 зависят от загрузчика классов. Согласно Javadoc, исключение предназначено только для причины 1.
Самуил

1
Я проверил случай 2 и случай 3, это не NoClassDefFoundError, это файл ExceptionInInitializerError, файл 2.Class расположен, но возникла исключительная ситуация при инициализации статических переменных Файл Case 3.Class расположен, исключение возникло при инициализации статических блоков
Майкл

1
@Michael, по этой ссылке написано, что ваша трассировка стека будет слишком показывать NoClassDefFoundErrorдля этого случая: archive.is/YPbYI#selection-2107.0-2115.13
Pacerier

15

NoClassDefFoundErrorозначает, что класс присутствует в пути к классам в Compile time, но он не существует в пути к классам в Runtime.

Если вы используете Eclipse, убедитесь, что у вас есть и shapes, linepointsи spaceobjectsкак записи в .classpathфайле.


1
Как справиться с этим во время выполнения через try / catch ?
Maveň ツ

5
Этот ответ не так, как вы пишете. Правильно было бы: «ОДНОЙ возможной причиной этой ошибки является…». Но могут быть и другие причины, по которым вы получаете эту ошибку, например, при загрузке файла JAR во время выполнения с загрузчиком классов.
Эльму

13

если вы получили одну из этих ошибок при компиляции и запуске:

* NoClassDefFoundError

* Error: Could not find or load main class hello

* Exception in thread "main" java.lang.NoClassDefFoundError:javaTest/test/hello 
(wrong name: test/hello)
        at java.lang.ClassLoader.defineClass1(Native Method)
        at java.lang.ClassLoader.defineClass(Unknown Source)
        at java.security.SecureClassLoader.defineClass(Unknown Source)
        at java.net.URLClassLoader.defineClass(Unknown Source)
        at java.net.URLClassLoader.access$100(Unknown Source)
        at java.net.URLClassLoader$1.run(Unknown Source)
        at java.net.URLClassLoader$1.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at sun.launcher.LauncherHelper.checkAndLoadMain(Unknown Source)

-------------------------- РЕШЕНИЕ -----------------------

проблема в основном в организации пакетов. Вы должны расположить ваши классы в папках должным образом в соответствии с классификациями пакетов в вашем исходном коде.

On Compiling process use this command:

javac -d . [FileName.java]

To Run the class please use this command:

java [Package].[ClassName]

"-D." Команда javac делает свое дело, создавая структуру папок пакетов вместо того, чтобы помещать все файлы .class в корневой каталог, спасибо!
Хорхе Сампайо

9
java.lang.NoClassDefFoundError

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


15
Как это сделать?
Нарендра Сингх,

зависит от контекста, который вы запрашиваете.
sschrass

6

Исключение определения класса не возникает, если предполагаемый класс не найден в пути к классам. Во время компиляции класс: класс был сгенерирован из компилятора Java, но каким-то образом во время выполнения зависимый класс не найден.

Давайте рассмотрим один простой пример:

public class ClassA{
public static void main(String args[]){
     //Some gibberish Code...
     String text = ClassB.getString();
     System.out.println("Text is :" + text);
}

}

public class ClassB{
    public static String getString(){
      return "Testing Some Exception";
 }
}

Теперь давайте предположим, что вышеупомянутые два исходных кода Java размещены в некоторой папке, скажем, «NoClassDefinationFoundExceptionDemo»

Теперь откройте оболочку (при условии, что Java уже настроена правильно)

  1. Перейдите в папку «NoClassDefinationFoundExceptionDemo»
  2. Компилировать исходные файлы Java javac ClassB javac ClassA
  3. Оба файла успешно скомпилированы и сгенерированы файлы классов в той же папке, что и ClassA.class и ClassB.class
  4. Теперь, так как мы перенаправляем ClassPath в текущий рабочий каталог, мы выполняем следующую команду java -cp. ClassA и он успешно работал, и вы увидите вывод на экране
  5. Теперь допустим, вы удалили файл ClassB.class из Present Directory. и теперь вы выполняете команду снова. java -cp. ClassA Теперь он будет приветствовать вас с NoClassDefFoundException. поскольку ClassB, который является зависимостью для ClassA, не найден в пути к классам (т. е. присутствует рабочий каталог).

5

NoClassDefFoundError в Java:

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

NoClassDefFoundError возникнет, если класс присутствовал во время компиляции, но не был доступен в пути к классам Java во время выполнения. Обычно вы увидите строку ниже в журнале, когда получите NoClassDefFoundError: Исключение в потоке "main" java.lang.NoClassDefFoundError

Возможные причины:

  1. Класс недоступен в Java Classpath.

  2. Возможно, вы запускаете программу с помощью команды jar, а класс не определен в атрибуте ClassPath файла манифеста.

  3. Любой сценарий запуска переопределяет переменную среды Classpath.

  4. Поскольку NoClassDefFoundError является подклассом java.lang.LinkageError, он также может появиться, если одна из его зависимостей, такая как нативная библиотека, может быть недоступна.

  5. Проверьте наличие java.lang.ExceptionInInitializerError в файле журнала. NoClassDefFoundError из-за сбоя статической инициализации встречается довольно часто.

  6. Если вы работаете в среде J2EE, то видимость Class среди нескольких Classloader также может вызвать java.lang.NoClassDefFoundError, подробное обсуждение см. В разделе примеров и сценариев.

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

  1. Убедитесь, что все необходимые классы Java включены в путь к классам приложения. Самая распространенная ошибка - не включать все необходимые классы перед началом выполнения приложения Java, которое зависит от некоторых внешних библиотек.

  2. Путь к классу приложения правильный, но переменная среды Classpath переопределяется перед выполнением приложения.

  3. Убедитесь, что вышеупомянутая ExceptionInInitializerError не отображается в трассировке стека вашего приложения.

Ресурсы:

3 способа решить java.lang.NoClassDefFoundError в Java J2EE

java.lang.NoClassDefFoundError - Как решить ошибку No Class Def Found Found


3

Если ваш проект находится в пакете, как com.blahcodeи ваш класс называется Main, скомпилированные файлы могут быть выведены в структуре каталогов, как ./out/com/blahcode/Main.class. Это особенно верно для IntelliJ IDEA.

При попытке запустить из оболочки или cmd, вам нужно перейти cdк тому, что содержится comв качестве подкаталога.

cd out
java -classpath . com.blahcode.Main

1

Проработав над проектом NetBeans в течение многих месяцев, я внезапно получил сообщение NoClassDefFoundError вскоре после получения предупреждения «Недостаточно памяти». Выполнение чистой перестройки не помогло, но при закрытии Netbeans и повторном открытии проекта не было сообщений об ошибках.


1

Этот ответ относится к ошибке java.lang.NoClassDefFoundError, возникающей в службе :

Моя команда недавно увидела эту ошибку после обновления rpm, который предоставлял сервис. Rpm и программное обеспечение внутри него были созданы с Maven, поэтому казалось, что у нас была зависимость от времени компиляции, которая просто не была включена в rpm.

Однако при расследовании класс, который не был найден, находился в том же модуле, что и несколько классов в трассировке стека. Кроме того, это был не тот модуль, который был добавлен в сборку только недавно. Эти факты указывают на то, что это может не быть проблемой зависимости Maven.

Возможное решение: перезапустите сервис!

Похоже, что обновление rpm сделало недействительным дескриптор файла сервиса в базовом файле jar. Затем служба увидела класс, который не был загружен в память, искала его в своем списке дескрипторов jar-файлов и не смогла найти его, поскольку дескриптор файла, из которого он мог загрузить класс, был признан недействительным. Перезапуск службы заставил его перезагрузить все свои файловые дескрипторы, что позволило ему загрузить тот класс, который не был найден в памяти сразу после обновления rpm.

Надеюсь, что конкретный случай кому-то поможет.


1

Я столкнулся с проблемой сегодня. У меня есть проект Android, и после его включения multidexпроект больше не запускается.

Причина была в том, что я забыл вызвать конкретный мультидексный метод, который должен быть добавлен в Application classи вызван перед всем остальным.

 MultiDex.install(this);

Следуйте этому руководству, чтобы правильно включить мультидекс. https://developer.android.com/studio/build/multidex.html

Вы должны добавить эти строки в свой класс Application

 @Override
  protected void attachBaseContext(Context base) {
     super.attachBaseContext(base);
     MultiDex.install(this);
  }

1

Для моего проекта проблема была в том, что браузер Chrome и chromedriver не были совместимы. У меня была очень старая версия драйвера, которая не могла даже открыть браузер. Я только что скачал последнюю версию и проблема решена. Как я обнаружил проблему? Поскольку я запускал свой проект, используя собственный драйвер Firefox Selenium со старой версией FF, встроенной в мое приложение, я понял, что проблема заключается в несовместимости браузера и драйвера.

Надеюсь, что это может помочь любому с такой же проблемой, как моя, которая генерировала это же сообщение об ошибке.


0

Мои два цента в этой цепочке:

Убедитесь, что путь к классу содержит полные пути ( /home/user/lib/some_lib.jarвместо ~/lib/some_lib.jar), в противном случае вы все равно можете столкнуться с NoClassDefFoundErrorошибкой.


Это верно отчасти, но это сложнее. 1) Вы можете использовать относительные пути в пути к классам, но они должны быть разрешены JVM ... относительно текущего каталога JVM. Это делает их хрупкими . 2) Вы можете использовать ~и другие метасимволы оболочки при установке переменной окружения classpath, но только при условии, что механизм, который вы используете для установки переменной, расширяет их до реальных путей. Если вы используете bash, вы можете получить «смешанные» результаты. Например, посмотрите, что вы получаете при вводе echo ~:~в командной строке. Первый ~расширен, а второй нет.
Стивен С.

0

Я получаю 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;
            }
        });
    }
}

0

Это случилось со мной в Android Studio.

Решение, которое сработало для меня: просто перезапустите студию.


0

У меня была такая же проблема с моей разработкой Android с использованием Android studio. Предоставленные решения являются общими и не помогли мне (по крайней мере, для меня). После нескольких часов исследований я нашел следующее решение и может помочь разработчикам Android, которые занимаются разработкой с использованием Android Studio. измените настройку, как показано ниже: «Настройки» -> «Сборка», «Выполнение», «Развертывание» -> «Мгновенный запуск» -> снимите флажок с первого параметра.

С этим изменением я в порядке. Надеюсь, это поможет моим друзьям.


0

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

-libraryJars "path.to.a.missing.jar.library".

Это объясняет, почему компиляция и запуск работают нормально, учитывая, что jar есть, а clean & build завершается неудачно. Не забудьте определить новые добавленные библиотеки jar в настройках Proguard!

Обратите внимание, что сообщения об ошибках от Proguard на самом деле не соответствуют стандарту, так как их легко спутать с аналогичными сообщениями муравья, которые приходят, когда банка вообще нет. Только в самом низу будет небольшой намек на беду. Следовательно, вполне логично начать поиск традиционных ошибок пути к классам и т. Д., Но это будет напрасно.

Очевидно, что исключение NoClassDefFound будет результатом при запуске, например, созданного в результате исполняемого файла jar, созданного на основе отсутствия согласованности proguard. Некоторые называют это Proguard "Ад"


0

Я использую плагин FileSync для Eclipse, чтобы я мог выполнять отладку в режиме реального времени на Tomcat, и я получил, NoClassFoundErrorпотому что я добавил запись синхронизации для binкаталога в рабочую область Eclipse => classesв metadatafor для Tomcat, но также не добавил синхронизацию папок для extlibкаталога в Eclipse.=>

C:\Users\Stuart\eclipse-workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\webapps\myApp\WEB-INF\lib


0

Я разрабатываю приложение на основе Eclipse, также известное как RCP (Rich Client Platform) . И я столкнулся с этой проблемой после рефакторинга (перевод одного класса из плагина в новый).

Очистка проекта и обновление Maven не помогли.

Проблема была вызвана активатором пакета, который не обновлялся автоматически. Ручное обновление Bundle-Activator в MANIFEST.MF в новом плагине устранило мою проблему.


0

Если вы недавно добавили поддержку мультидекса в Android Studio, как это:

// To Support MultiDex
implementation 'com.android.support:multidex:1.0.1'

так что ваше решение просто расширяется от MultiDexApplication вместо Application

public class MyApp extends MultiDexApplication {

0

Если вы используете более одного модуля, вы должны иметь

dexOptions {
    preDexLibraries = false
}

в вашем файле сборки.


0

Проверьте это, если у вас есть статический обработчик в вашем классе. Если это так, пожалуйста, будьте осторожны, потому что статический обработчик может быть запущен только в потоке с петлителем, сбой может быть вызван следующим образом:

1. Во-первых, создайте экземпляр класса в простом потоке и поймайте сбой.

2. затем вызовите метод поля Class в главном потоке, вы получите NoClassDefFoundError.

вот тестовый код:

public class MyClass{
       private static  Handler mHandler = new Handler();
       public static int num = 0;
}

в вашем методе onCrete Основной операции добавьте часть кода теста:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    //test code start
    new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                MyClass myClass = new MyClass();
            } catch (Throwable e) {
                e.printStackTrace();
            }
        }
    }).start();

    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    MyClass.num = 3;
    // end of test code
}

Есть простой способ исправить это, используя handlerThread для инициализации обработчика:

private static Handler mHandler;
private static HandlerThread handlerThread = new HandlerThread("newthread");
static {
    handlerThread.start();
    mHandler = new Handler(handlerThread.getLooper(), mHandlerCB);
}

0

Не используйте тестовые классы вне модуля

У меня нет решения, просто еще один вариант случая «присутствует при компиляции, отсутствует во время выполнения».

Я пытался использовать очень удобный метод из тестового класса JUnit из другого тестового класса, который находится в другом модуле. Это нет-нет, так как тестовый код не является частью упакованного jar, но я не понял, потому что он кажется видимым для пользовательского класса из Eclipse.

Моим решением было поместить метод в существующий класс утилит, который является частью производственного кода.


0

В моей среде я сталкиваюсь с этой проблемой в модульном тестировании. После добавления одной библиотечной зависимости в * .pom это исправлено.

например:

сообщение об ошибке:

java.lang.NoClassDefFoundError: com/abc/def/foo/xyz/Iottt

П:

<dependency>
    <groupId>com.abc.def</groupId>
    <artifactId>foo</artifactId>
    <scope>test</scope>
</dependency>

0

Я получил эту ошибку после изменения ветки Git. Для конкретного случая Eclipse в каталоге .settings были пропущенные строки для файла org.eclipse.wst.common.component. Как вы можете видеть ниже

Восстановление зависимостей проекта с помощью Maven Install поможет.

введите описание изображения здесь


0

если вы используете gradlew, перейдите к правильной версии Gradle ./gradle/wrapper/gradle-wrapper.propertiesи перейдите distributionUrlна нее.

Если вы используете JDK14, попробуйте

distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-bin.zip

-1

Это часто случается с моими устройствами genymotion. Убедитесь, что на диске, где установлен Genymotion, имеется достаточно свободного места.


У вас есть ссылки на это?
Вай Ха Ли

Нет, у меня просто регулярно заканчивается свободное место на диске, и если я не освобождаю достаточное количество + удаляю / переустанавливаю виртуальное устройство Genymotion, я продолжаю получать эту ошибку.
Тотем
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.