Что означает «Не удалось найти или загрузить основной класс»?

Распространенная проблема, с которой сталкиваются новые разработчики Java, заключается в том, что их программы не работают с сообщением об ошибке: «Не удалось найти или загрузить основной класс ...`

Что это значит, что вызывает это, и как это исправить?

Комментарии к вопросу (1)
Решение

Синтаксис команды java < class-name >


Прежде всего, вам нужно понять правильный способ запуска программы с помощью команды java (или javaw).

Нормальный синтаксис 1 < / sup > это:

    java [  ... ]  [ ...]

где < option > - опция командной строки (начиная с символа "-"), < class-name > - это полностью квалифицированное имя класса Java, а< argument > является произвольный аргумент командной строки, который передается вашему приложению.

1 - есть второй синтаксис для «исполняемых» файлов JAR, который я опишу внизу.& Лт; / sup >

Полностью квалифицированное имя (FQN) для класса обычно пишется так же, как в исходном коде Java; например.

    packagename.packagename2.packagename3.ClassName

Однако некоторые версии команды java позволяют использовать косые черты вместо периодов; например.

    packagename/packagename2/packagename3/ClassName

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

Вот пример того, как должна выглядеть команда java:

    java -Xmx100m com.acme.example.ListUsers fred joe bert

Вышеуказанное приведет к тому, что команда java сделает следующее:

  1. Ищите скомпилированную версию класса `com.acme.example.ListUsers.

  2. Загрузите класс.

  3. Убедитесь, что в классе есть метод main с signature , return type и модификаторами , заданными public static void main (String []). (Примечание, имя аргумента метода является НЕ частью подписи.)

  4. Назовите этот метод, передав ему аргументы командной строки («fred», «joe», «bert») как «String []».

Причины, по которым Java не может найти класс


Когда вы получите сообщение «Не удалось найти или загрузить основной класс ...«Это означает, что первый шаг не удался. Команда java не смогла найти класс. И действительно, "..."в сообщении будет полностью квалифицированное имя класса , которое ищет" Java ".

Так почему же он не может найти класс??

Причина № 1 - вы допустили ошибку с аргументом имени класса


Первая вероятная причина в том, что вы, возможно, указали неправильное имя класса. (Или ... правильное имя класса, но в неправильной форме.) Учитывая приведенный выше пример, вот несколько неправильных способов указать имя класса:

  • Пример № 1 - простое имя класса:

    Ява Листусер

    Когда класс объявлен в пакете, таком как com.acme.example, вы должны использовать полное имя класса , включая имя пакета в команде java; например.

    java com.acme.example.ListUser
  • Пример № 2 - имя файла или путь, а не имя класса:

    java ListUser.class
    
    java com / acme / example / ListUser.class
  • Пример № 3 - имя класса с неправильным корпусом:

    java com.acme.example.listuser
  • Пример № 4 - опечатка

    java com.acme.example.mistuser
  • Пример № 5 - имя исходного файла

    java ListUser.java
  • Пример № 6 - вы полностью забыли имя класса

    Ява много аргументов

Причина № 2 - классная дорожка приложения указана неправильно


Вторая вероятная причина заключается в том, что имя класса является правильным, но команда java не может найти класс. Чтобы понять это, вам нужно понять концепцию «классового пути». Это хорошо объясняется документацией Oracle:

Так ... если вы правильно указали имя класса, следующее, что нужно проверить, это то, что вы правильно указали путь класса:

  1. Прочитайте три документа, связанных выше. (Да ... ЧИТАЙТЕ их. Важно, чтобы программист Java понимал хотя бы основы работы механизмов Java classpath.)

  2. Посмотрите на командную строку и / или переменную среды CLASSPATH, которая действует при запуске команды java. Убедитесь, что имена каталогов и файлов JAR верны.

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

  4. Убедитесь, что класс (упомянутый в сообщении об ошибке) может быть расположен на эффективном пути класса.

  5. Обратите внимание, что синтаксис classpath отличается для Windows от Linux и Mac OS. (Разделитель classpath - ;в Windows и :в других. Если вы используете неправильный разделитель для своей платформы, вы не получите явного сообщения об ошибке. Вместо этого вы получите несуществующий файл или каталог на пути, который будет молча игнорироваться.)

Причина № 2а - неправильный каталог находится на пути к классу


Когда вы помещаете каталог в classpath, он условно соответствует корню квалифицированного пространства имен. Классы расположены в структуре каталогов под этим корнем путем сопоставления полностью квалифицированного имени с именем пути . Так, например, если «/usr/local/acme/classes» находится на пути к классу, то, когда JVM ищет класс с именем com.acme.example.Foon, он будет искать файл «.class» с этим pathname:

  /usr/local/acme/classes/com/acme/example/Foon.class

Если бы вы поместили «/ usr / local / acme / classes / com / acme / example» в classpath, то JVM не смог бы найти класс.

Причина № 2b - путь подкаталога не соответствует FQN


Если ваши классы FQN - com.acme.example.Foon, то JVM будет искать «Foon.class» в каталоге «com / acme / example»:

  • Если структура вашего каталога не соответствует именованию пакета согласно шаблону выше, JVM не найдет ваш класс.

  • Если вы попытаетесь переименовать класс, переместив его, это также потерпит неудачу ... но исключение stacktrace будет другим. Он может сказать что-то вроде этого:

    Вызывается: java.lang.NoClassDefFoundError: < path > (неправильное имя: < имя >)

    потому что FQN в файле класса не соответствует тому, что ожидает найти загрузчик класса.

Чтобы привести конкретный пример, предположим, что:

  • Вы хотите запустить com.acme.example.Foon class,

  • полный путь к файлу: /usr/local/acme/classes/com/acme/example/Foon.class,

  • ваш текущий рабочий каталог - / usr / local / acme / classes / com / acme / example /,

тогда:

# wrong, FQN is needed
java Foon

# wrong, there is no `com/acme/example` folder in the current working directory
java com.acme.example.Foon

# wrong, similar to above
java -classpath . com.acme.example.Foon

# fine; relative classpath set
java -classpath ../../.. com.acme.example.Foon

# fine; absolute classpath set
java -classpath /usr/local/acme/classes com.acme.example.Foon

Примечания:

  • Параметр -classpath можно сократить до -cp в большинстве выпусков Java. Проверьте соответствующие записи руководства для java, javac и так далее.

  • Тщательно продумайте при выборе абсолютного и относительного пути имен в classpaths. Помните, что относительный путь может «сломаться», если текущий каталог изменяется.

Причина № 2с - зависимости отсутствуют в классе


Classpath должен включать все другие (несистемные) классы, от которых зависит ваше приложение. (Классы системы расположены автоматически, и вам редко нужно беспокоиться об этом.) Чтобы основной класс загружался правильно, JVM необходимо найти:

  • сам класс.

  • все классы и интерфейсы в иерархии суперклассов (например,. см. https://stackoverflow.com/questions/42880748)

  • все классы и интерфейсы, на которые ссылаются посредством переменных или переменных объявлений, или методный вызов или выражения доступа к полю.

(Примечание: спецификации JLS и JVM позволяют JVM загружать классы «лазильно», и это может повлиять на исключение classloader.)

Причина № 3 - класс был объявлен не в том пакете


Иногда случается, что кто-то помещает файл исходного кода в

неправильная папка в дереве исходного кода, или они пропускают декларацию package. Если вы сделаете это в IDE, компилятор IDE немедленно расскажет вам об этом. Точно так же, если вы используете приличный инструмент сборки Java, инструмент будет запускать javac таким образом, чтобы обнаружить проблему. Однако, если вы создаете свой код Java вручную, вы можете сделать это таким образом, чтобы компилятор не заметил проблемы, и полученный файл «.class» находится не в том месте, в котором вы ожидаете.

Все еще не могу найти проблему?


Есть много вещей, которые нужно проверить, и что-то легко пропустить. Попробуйте добавить опцию -Xdiag в командную строку java (как первое после java). Он будет выводить различные вещи о загрузке класса, и это может дать вам подсказки относительно реальной проблемы.

Кроме того, рассмотрите возможные проблемы, вызванные копированием и вклеиванием невидимых или не-ASCII символов с веб-сайтов, документов и так далее. И рассмотрим «гомоглифы», если две буквы или символы выглядят одинаково ... но нет.


Синтаксис java -jar < jar file >


Альтернативный синтаксис, используемый для «исполняемых» файлов JAR, выглядит следующим образом:

  java [  ... ] -jar  [ ...]

например.

  java -Xmx100m -jar /usr/local/acme-example/listuser.jar fred

В этом случае имя класса точки входа (т.е. com.acme.example.ListUser) и classpath указаны в MANIFEST файла JAR.


IDE


Типичная Java IDE поддерживает запуск приложений Java в самой IDE JVM или в дочернем JVM. Они как правило защищены от этого конкретного исключения, потому что IDE использует свои собственные механизмы для построения пути класса во время выполнения, идентифицировать основной класс и создать командную строку java. Однако это исключение все еще возможно, если вы делаете вещи за задней частью IDE. Например, если вы ранее настроили Application Launcher для своего приложения Java в Eclipse, и вы затем переместили файл JAR, содержащий &"main &" класс в другое место в файловой системе не сообщая Eclipse , Eclipse невольно запустит JVM с неправильным классом.

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

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


Другие ссылки


Комментарии (11)

Если ваше имя исходного кода - HelloWorld.java, ваш скомпилированный код будет HelloWorld.class.

Вы получите эту ошибку, если позвоните по ней, используя:

java HelloWorld.class

Вместо этого используйте это:

java HelloWorld
Комментарии (8)

Если ваши классы находятся в пакетах , вам нужно cd в корневой каталог вашего проекта и запустить, используя полностью квалифицированное имя класса (packageName.MainClassName).

Пример:

Мои занятия здесь:

D:\project\com\cse\

Полностью квалифицированное имя моего основного класса:

com.cse.Main

Поэтому я возвращаюсь в каталог корневых проектов:

D:\project

Затем введите команду java:

java com.cse.Main
  • Этот ответ предназначен для спасения начинающих программистов Java от разочарования, вызванного распространенной ошибкой, я рекомендую вам прочитать принятый ответ для более глубокого знания о классе Java.*
Комментарии (2)

Если вы определяете основной класс и основной метод в package , вы должны запустить его через иерархический каталог, используя полное имя класса (packageName.MainClassName).

Предположим, что есть файл исходного кода (Main.java):

package com.test;

public class Main {

    public static void main(String[] args) {
        System.out.println("salam 2nya\n");
    }
}

Для запуска этого кода вы должны поместить Main.Class в пакет, например каталог ./com/test/Main.Java. А в корневом каталоге используйте java com.test.Main.

Комментарии (6)

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

javac HelloWorld.java
java -cp . HelloWorld
Комментарии (5)

Что помогло мне, так это указание classpath в командной строке, например:

  1. Создайте новую папку C: \ temp

  2. Создайте файл Temp.java в C: \ temp со следующим классом:

     публичный класс Temp {
         открытый статический пустотный главный (строка args []) {
             System.out.println (args [0]) ;
         }
     }
  3. Откройте командную строку в папке C: \ temp и напишите следующую команду для компиляции класса Temp:

     javac Temp.java
  4. Запустите скомпилированный класс Java, добавив опцию -classpath, чтобы JRE знал, где найти класс:

     java -classpath C: \ temp Temp Hello!
Комментарии (7)

Согласно сообщению об ошибке («Не удалось найти или загрузить основной класс»), существует две категории проблем:

  1. Основной класс не может быть найден
  2. Основной класс не может быть загружен (этот случай не полностью обсуждается в принятом ответе)

Основной класс не может быть найден , когда в полностью квалифицированном имени класса есть тип или неправильный синтаксис или он не существует в предоставленном пути класса .

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

Например:

public class YourMain extends org.apache.camel.spring.Main

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

Комментарии (11)

У меня была такая ошибка в этом случае:

java -cp lib.jar com.mypackage.Main

Работает с ;для Windows и :для Unix:

java -cp lib.jar; com.mypackage.Main
Комментарии (2)

Используйте эту команду:

java -cp . [PACKAGE.]CLASSNAME

Пример: если ваше имя класса Hello.class создано из Hello.java, используйте команду ниже:

java -cp . Hello

Если ваш файл Hello.java находится внутри пакета com.demo, используйте команду ниже

java -cp . com.demo.Hello

При JDK 8 часто случается, что файл класса присутствует в одной папке, но команда java ожидает classpath, и по этой причине мы добавляем -cp . принять текущую папку в качестве ссылки для classpath.

Комментарии (8)

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

Не удалось найти или загрузить основной класс xxx Linux

Я просто удалил эту ссылку, добавил ее снова, и она снова работала нормально.

Комментарии (5)

Попробуйте -Xdiag .

Ответ Стива С хорошо охватывает возможные случаи, но иногда определить, не может ли класс быть найден или загружен , может быть не так просто. Используйте java -Xdiag (начиная с JDK & nbsp; 7). Это распечатывает хорошую трассировку стека, которая дает подсказку о том, что означает сообщение Не удалось найти или загрузить сообщение основного класса.

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

Комментарии (0)

В этом случае у вас есть:

Не удалось найти или загрузить основной класс ?classpath

Это потому, что вы используете «-classpath», но тире не та же самая тире, которая используется «java» в командной строке. У меня была эта проблема копирования и вставки из Notepad в cmd.

Комментарии (1)

У меня была та же проблема, и я наконец нашел свою ошибку :) Я использовал эту команду для компиляции, и она работала правильно:

javac -cp "/home/omidmohebbi/AAAATest/jars/core-1.7.jar:/home/omidmohebbi/AAAATest/jars/javase-1.7.jar:/home/omidmohebbi/AAAATest/jars/qrgen-1.2.jar" qrcode.java

Но эта команда не работала для меня (я не мог найти или загрузить основной класс qrcode):

java -cp "/home/omidmohebbi/AAAATest/jars/core-1.7.jar:/home/omidmohebbi/AAAATest/jars/javase-1.7.jar:/home/omidmohebbi/AAAATest/jars/qrgen-1.2.jar" qrcode

Наконец я просто добавил символ ':' в конце пути класса, и проблема была решена:

java -cp "/home/omidmohebbi/AAAATest/jars/core-1.7.jar:/home/omidmohebbi/AAAATest/jars/javase-1.7.jar:/home/omidmohebbi/AAAATest/jars/qrgen-1.2.jar:" qrcode
Комментарии (0)

В моем случае появилась ошибка, потому что я предоставил имя исходного файла вместо имени класса.

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

Комментарии (1)

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

Я скомпилировал это так:

javac HelloWorld.java

И я попытался запустить также с тем же расширением:

java Helloworld.java

Когда я удалил .java и переписал команду как java HelloWorld, программа работала отлично. :)

Комментарии (2)

Местоположение файла класса: C: \ test \ com \ company

Имя файла: Main.class

Полностью квалифицированное название класса: com.company.Main

Команда командной строки:

java  -classpath "C:\test" com.company.Main

Обратите внимание, что путь к классу НЕ включает \ com \ company

Комментарии (0)

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

java -cp C:/java/MyClasses C:/java/MyClasses/utilities/myapp/Cool  

вместо:

java -cp C:/java/MyClasses utilities/myapp/Cool   

Я думал, что значение полностью квалифицированного означает включить полное имя пути вместо полного имени пакета.

Комментарии (2)

Сначала установите путь, используя эту команду;

set path="paste the set path address"

Тогда вам нужно загрузить программу. Введите «cd (имя папки)» на сохраненном диске и скомпилируйте его. Например, если моя программа хранится на диске D, введите «D:» нажмите Enter и введите «cd (имя папки)».

Комментарии (3)

Что решило проблему в моем случае было:

Щелкните правой кнопкой мыши по проекту / классу, который вы хотите запустить, затем Run As - > Run Configurations. Затем вы должны либо исправить существующую конфигурацию, либо добавить новую следующим образом:

откройте вкладку «Classpath», нажмите «Дополнительно»...кнопка затем добавить ** bin` папку ** вашего проекта.

Комментарии (0)

Кажется, все ответы здесь направлены на пользователей Windows. Для Mac разделителем classpath является :, а не ;. Поскольку ошибка, устанавливающая путь к классу с использованием ;, не отбрасывается, это может быть трудно обнаружить при переходе с Windows на Mac.

Вот соответствующая команда Mac:

java -classpath ".:./lib/*" com.test.MyClass

Где в этом примере пакет com.test и папка lib также должна быть включена в classpath.

Комментарии (3)