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

Я попробовал оба примера в 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, но они имеют схожие концепции.

35 ответов

Решение

После компиляции кода вы получите .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, помогут вам не беспокоиться о путях к классам (а также о них) и сосредоточиться на коде! Тем не менее, эта ссылка объясняет, как установить classpath при выполнении в командной строке.

Я хотел бы исправить точку зрения других на 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();

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

  • NoClassDefFoundError

  • Ошибка: не удалось найти или загрузить главный класс привет

  • Исключение в потоке "main" java.lang.NoClassDefFoundError: javaTest/test/hello (неправильное имя: test/hello) в java.lang.ClassLoader.defineClass1(собственный метод) в java.lang.ClassLoader.defineClass (неизвестный источник) в java.security.SecureClassLoader.defineClass(неизвестный источник) в java.net.URLClassLoader.defineClass(неизвестный источник) в java.net.URLClassLoader.access$100(неизвестный источник) в java.net.URLClassLoader$1.run(неизвестный источник) в java.net.URLClassLoader$1.run(неизвестный источник) в java.security.AccessController.doPrivileged(собственный метод) в java.net.URLClassLoader.findClass(неизвестный источник) в java.lang.ClassLoader.loadClass (неизвестный источник) на солнце.misc.Launcher$AppClassLoader.loadClass(Неизвестный источник) в java.lang.ClassLoader.loadClass (Неизвестный источник) в sun.launcher.LauncherHelper.checkAndLoadMain(Неизвестный источник)

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

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

On Compiling process use this command:

javac -d . [FileName.java]

To Run the class please use this command:

java [Package].[ClassName]

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

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

java.lang.NoClassDefFoundError

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

NoClassDefFoundError в Java:

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

NoClassDefFoundError возникнет, если класс присутствовал во время компиляции, но не был доступен в java classpath во время выполнения. Обычно вы увидите строку ниже в журнале, когда получите 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

Исключение определения класса не возникает, если предполагаемый класс не найден в пути к классам. Во время компиляции класс: класс был сгенерирован из компилятора 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, не найден в пути к классам (то есть присутствует рабочий каталог).

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

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

cd out
java -classpath . com.blahcode.Main

Если вы «запускаете» класс из файла JAR, убедитесь, что вы начинаете с полного пути к JAR. Например (если ваш «основной класс» не указан в манифесте):.

      java -classpath "./dialer.jar" com.company.dialer.DialerServer 

И если есть какие-либо зависимости, такие зависимости от других JAR, вы можете решить такую ​​зависимость

  • либо путем добавления таких JAR (полный путь к каждому JAR) в путь к классу. Например
      java -classpath "./libs/phone.jar;./libs/anotherlib.jar;./dialer.jar" com.company.dialer.DialerServer
  • или путем редактирования манифеста JAR путем добавления в манифест «JAR зависимостей». Такой файл манифеста может выглядеть как
      Manifest-Version: 1.0
Class-Path: phone.jar anotherlib.jar
Build-Jdk-Spec: 1.8
Main-Class: com.company.dialer.DialerServer
  • или (если вы разработчик, имеющий исходные коды), вы можете использовать Maven для подготовки манифеста для вас, добавив в файл *.pom:
      <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <configuration>
        <archive>
            <manifest>
                <addClasspath>true</addClasspath>
                <mainClass>com.company.dialer.DialerServer</mainClass>
            </manifest>
        </archive>
    </configuration>
</plugin>

Обратите внимание, что в приведенном выше примере используется; в качестве разделителя в пути к классам (это действительно для платформы Windows). В Linux замените; от :

Например

      java -classpath ./libs/phone.jar:./libs/anotherlib.jar:./dialer.jar 
com.company.dialer.DialerServer

Этот ответ является специфическим для java.lang.NoClassDefFoundError, происходящего в сервисе:

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

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

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

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

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

Я столкнулся с проблемой сегодня. У меня есть проект 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);
  }

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

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

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

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

dexOptions {
    preDexLibraries = false
}

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

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

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

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

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

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

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

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

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

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

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

Если вы используете Eclipse, проверьте Run Configuration/Dependencies. Я столкнулся с этой проблемой при использовании внешнего файла jar, который был включен в путь/библиотеки сборки Java, но каким-то образом не был указан в конфигурации запуска/зависимостей.

Для пользователей Meteor или Cordova:

Это может быть вызвано используемой версией Java, для Meteor и Cordova пока придерживается версии 8.

1- Проверить доступные версии Java /usr/libexec/java_home -V и найдите путь к Java версии 8

2- Установите путь для Java версии 8
export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home

3- Проверьте, сделано ли это echo $JAVA_HOME

Продолжайте и продолжайте кодирование.

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

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

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

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

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

public class MyApp extends MultiDexApplication {

1) Первый метод: я решил эту проблему. Удалив некоторые классы зависимостей, удалите их из приведенного ниже кода. С этой проблемой я столкнулся на 4.2.2.

compile 'com.google.android.gms:play-services-gcm:11.0.4'
compile 'com.google.android.gms:play-services:11.0.4'

это дополнительные в моем коде, я удалил их

 dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
    exclude group: 'com.android.support', module: 'support-annotations'
})
compile files('libs/ypylibs.jar')
compile 'com.android.support:appcompat-v7:25.3.1'
compile 'com.google.android.gms:play-services-gcm:11.0.4'
compile 'com.google.android.gms:play-services:11.0.4'
compile 'com.google.android.gms:play-services-ads:11.0.4'
compile 'com.dailymotion.dailymotion-sdk-android:sdk:0.1.12'
compile 'org.apache.httpcomponents:httpcore:4.4.1'
compile 'commons-io:commons-io:1.3.2'
compile 'com.oguzdev:CircularFloatingActionMenu:1.0.2'
compile 'com.android.support:multidex:1.0.1'
compile 'com.android.support.constraint:constraint-layout:1.0.2'
testCompile 'junit:junit:4.12'

} (2) Метод: Другой способ решить эту проблему - создать новый класс Myapplication.

public class MyApplication extends Application {

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

}

затем добавьте его в файл mainfest и в тег приложения

 <application
    android:allowBackup="true"
    android:name=".gps.navigation.map.MyApplication"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme"></application>

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

например:

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

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

пом:

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

Решение Java 11 + eclipse:

Это решение для вас, если вы не используете module-info.java в вашем проекте eclipse, и вы добавили банки вручную вместо использования Maven / Gradle.

  1. Щелкните правой кнопкой мыши проект -> Путь сборки -> Настроить путь сборки -> вкладка библиотеки
  2. Удалите проблемную банку из пути к модулю
  3. Добавить банку в путь к классам

Подробнее здесь:В чем разница между модулем и классами в Eclipse?

Другие вопросы по тегам