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

Общей проблемой, которую испытывают новые разработчики Java, является то, что их программы не запускаются с сообщением об ошибке: Could not find or load main class ...

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

+1253
источник поделиться
52 ответа
  • 1
  • 2

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

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

Обычный синтаксис 1 таков:

    java [ <option> ... ] <class-name> [<argument> ...]

где <option> - это параметр командной строки (начинающийся с символа "-"), <class-name> - это полное имя класса Java, а <argument> - произвольный аргумент командной строки, который передается вашему приложению.
1 - There is a second syntax for "executable" JAR files which I will describe at the bottom.

Полное имя (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 с сигнатурой, типом возвращаемого значения и модификаторами, заданными public static void main(String[]). (Обратите внимание, что имя аргумента метода является НЕ частью подписи.)
  4. Вызовите этот метод, передав ему аргументы командной строки ("fred", "joe", "bert") как String[].

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

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

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

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

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

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

    java ListUser
    

    Когда класс объявлен в пакете, таком как 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 - вы полностью забыли имя класса

    java lots of arguments
    

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

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

Итак... если вы правильно указали имя класса, то следует проверить, правильно ли вы указали путь к классам:

  1. Прочитайте три документа, ссылки на которые приведены выше. (Да... ПРОЧИТАЙТЕ их. Важно, чтобы программист на Java понимал, по крайней мере, основы того, как работают механизмы пути классов Java.)
  2. Посмотрите на командную строку и/или переменную среды CLASSPATH, которая действует при запуске команды java. Проверьте правильность имен каталогов и файлов JAR.
  3. Если в пути к классам есть относительные имена путей, проверьте, правильно ли они разрешаются... из текущего каталога, действующего при запуске команды java.
  4. Убедитесь, что класс (упомянутый в сообщении об ошибке) находится в эффективном пути к классам.
  5. Обратите внимание, что синтаксис classpath отличается для Windows по сравнению с Linux и Mac OS. (Разделителем пути к классам является ; в Windows и : в других. Если вы используете неправильный разделитель для вашей платформы, вы не получите явного сообщения об ошибке. Вместо этого вы получите несуществующий файл или каталог в путь, который будет игнорироваться.)

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

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

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

Если бы вы поместили "/usr/local/acme/classes/com/acme/example" в путь к классам, то JVM не сможет найти класс.

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

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

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

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

    Caused by: java.lang.NoClassDefFoundError: <path> (wrong name: <name>)
    

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

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

  • Вы хотите запустить класс com.acme.example.Foon,
  • полный путь к файлу - /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 и т.д.
  • Тщательно продумайте выбор между абсолютными и относительными путями в classpath. Помните, что относительный путь может "сломаться", если текущий каталог изменится.

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

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

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

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

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

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

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

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


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

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

  java [ <option> ... ] -jar <jar-file-name> [<argument> ...]

например,

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

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


Иды

Типичная Java IDE поддерживает запуск приложений Java в самой IDE JVM или в дочерней JVM. Как правило, они защищены от этого конкретного исключения, поскольку в среде IDE используются собственные механизмы для создания пути к классам среды выполнения, определения основного класса и создания командной строки java.

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

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

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


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

+1126
источник

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

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

java HelloWorld.class

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

java HelloWorld
+228
источник
другие ответы

Связанные вопросы


Похожие вопросы

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

Пример:

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

D:\project\com\cse\

Полное имя моего основного класса:

com.cse.Main

Так что я cd обратно в корневой директории проекта:

D:\project

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

java com.cse.Main

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

+128
источник

Если вы определяете основной класс и метод main в 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.

+58
источник

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

javac HelloWorld.java
java -cp . HelloWorld
+42
источник

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

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

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

    public class Temp {
        public static void main(String args[]) {
            System.out.println(args[0]);
        }
    }
    
  • Откройте командную строку в папке C:\temp и напишите следующую команду для компиляции класса Temp:

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

    java -classpath C:\temp Temp Hello!
    
+34
источник

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

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

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

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

Например:

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

Если camel- spring не включен, эта ошибка будет сообщена.

+24
источник

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

java -cp lib.jar com.mypackage.Main

Он работает с ; для Windows и : для Unix:

java -cp lib.jar; com.mypackage.Main
+16
источник

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

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

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

+15
источник

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

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.

+14
источник

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

Стив С ответ хорошо описывает возможные случаи, но иногда определить, невозможно ли найти или загрузить класс, может быть не так просто. Используйте java -Xdiag (с JDK 7). Это выдает красивую стеклу, которая дает подсказку тому, что сообщение Could not find or load main class средства сообщения Could not find or load main class.

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

+13
источник

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

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

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

+9
источник

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

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

+7
источник

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

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
+7
источник

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

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

вместо:

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

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

+6
источник

enter image description here

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

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

Полностью определенное имя класса: com.company.Main

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

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

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

+6
источник

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

Я собрал его так:

javac HelloWorld.java

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

java Helloworld.java

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

+6
источник

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

set path="paste the set path address"

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

+5
источник

Какая исправленная проблема в моем случае была:

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

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

+5
источник

Все ответы здесь направлены на пользователей Windows. Для Mac разделитель классов class :, а не ;. В качестве параметра ошибки путь к классам с использованием ; не выбрасывается, тогда это может быть трудно обнаружить, если перейти от Windows к Mac.

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

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

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

+5
источник

Если вы используете Maven для создания JAR файла, обязательно укажите основной класс в файле pom.xml:

<build>
    <plugins>
        <plugin>
            <artifactId>maven-jar-plugin</artifactId>
            <configuration>
                <archive>
                    <manifest>
                        <mainClass>class name us.com.test.abc.MyMainClass</mainClass>
                    </manifest>
                </archive>
            </configuration>
        </plugin>
    </plugins>
</build>
+5
источник

В Windows поместите .; в значение CLASSPATH в начале.

. (точка) означает "смотреть в текущем каталоге". Это постоянное решение.

Также вы можете установить его "один раз" с помощью набора CLASSPATH=%CLASSPATH%;.. Это будет продолжаться до тех пор, пока откроется ваше окно cmd.

+4
источник

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

Windows (тестируется с 7) не принимает специальные символы (например, á) в именах классов и пакетов. Linux, однако.

Я узнал об этом, когда я построил .jar в NetBeans и попытался запустить его в командной строке. Он работал в NetBeans, но не в командной строке.

+4
источник

В Java, когда вы иногда запускаете JVM из командной строки с помощью исполняемого файла java и пытаетесь запустить программу из файла класса с открытым статическим void main (PSVM), вы можете столкнуться с приведенной ниже ошибкой, даже если classpath для JVM является точной и файл класса присутствует в пути к классам:

Error: main class not found or loaded

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

Ссылка: https://www.computingnotes.net/java/error-main-class-not-found-or-loaded/

+3
источник

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

[name of the package].[Class Name] [arguments]

Скажем, ваш класс называется CommandLine.class, и код выглядит следующим образом:

package com.tutorialspoint.java;

    /**
     * Created by mda21185 on 15-6-2016.
     */

    public class CommandLine {
        public static void main(String args[]){
            for(int i=0; i<args.length; i++){
                System.out.println("args[" + i + "]: " + args[i]);
            }
        }
    }

Затем вы должны cd в папку src, и команда, которую вам нужно запустить, будет выглядеть так:

java com.tutorialspoint.java.CommandLine this is a command line 200 -100

И вывод в командной строке будет:

args[0]: this
args[1]: is
args[2]: a
args[3]: command
args[4]: line
args[5]: 200
args[6]: -100
+3
источник

При запуске java с параметром -cp, как описано в Windows PowerShell, вы можете получить ошибку, которая выглядит примерно так:

The term `ClassName` is not recognized as the name of a cmdlet, function, script ...

Чтобы PowerShell принял команду, аргументы параметра -cp должны содержаться в кавычках, как в:

java -cp 'someDependency.jar;.' ClassName

Формирование команды таким образом должно позволить Java обрабатывать аргументы classpath правильно.

+3
источник

Иногда, в некоторых онлайн-компиляторах, которые вы могли бы попробовать, вы получите эту ошибку, если не пишете public class [Classname], а просто class [Classname].

+3
источник

Я также сталкивался с подобными ошибками при тестировании соединения Java MongoDB JDBC. Я думаю, что хорошо подвести итог моему окончательному решению коротким, чтобы в будущем кто-то мог напрямую изучить две команды и хорошо продолжать дальше.

Предположим, вы находитесь в каталоге, где есть файл Java и внешние зависимости (файлы JAR).

Обобщение:

javac -cp mongo-java-driver-3.4.1.jar JavaMongoDBConnection.java
  • -cp - аргумент classpath; передавать все зависимые файлы JAR по одному
  • *.java - это файл класса Java, который имеет основной метод. SDSD

Бег:

java -cp mongo-java-driver-3.4.1.jar: JavaMongoDBConnection
  • Пожалуйста, наблюдайте за двоеточием (Unix)/запятой (Windows) после того, как все файлы JAR зависимости зависят от конца
  • В конце обратите внимание на имя основного класса без какого-либо расширения (нет.class или.java)
+3
источник

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

Во время работы пользователь может не иметь доступа к файлу JAR или одному из каталогов пути. Например, рассмотрим:

Jar файл в /dir1/dir2/dir3/myjar.jar

Пользователь1, которому принадлежит файл JAR, может сделать:

# Running as User1
cd /dir1/dir2/dir3/
chmod +r myjar.jar

Но это все равно не работает:

# Running as User2
java -cp "/dir1/dir2/dir3:/dir1/dir2/javalibs" MyProgram
Error: Could not find or load main class MyProgram

Это связано с тем, что у работающего пользователя (User2) нет доступа к dir1, dir2, javalibs или dir3. Это может привести кого-то в бешенство, когда Пользователь1 сможет увидеть файлы и получить к ним доступ, но ошибка по-прежнему возникает для Пользователя2.

+3
источник

Я получил эту ошибку после выполнения mvn eclipse:eclipse Это немного испортило мой файл .classpath.

Чтобы изменить строки в .classpath из

<classpathentry kind="src" path="src/main/java" including="**/*.java"/>
<classpathentry kind="src" path="src/main/resources" excluding="**/*.java"/>

to

<classpathentry kind="src" path="src/main/java" output="target/classes" />
<classpathentry kind="src" path="src/main/resources" excluding="**"  output="target/classes" />
+2
источник
  • 1
  • 2

Посмотрите другие вопросы по меткам или Задайте вопрос