Общая проблема, с которой сталкиваются новые Java-разработчики, заключается в том, что их программы не запускаются с сообщением об ошибке: Could not find or load main class ...
Что это значит, что вызывает и как это исправить?
Общая проблема, с которой сталкиваются новые Java-разработчики, заключается в том, что их программы не запускаются с сообщением об ошибке: Could not find or load main class ...
Что это значит, что вызывает и как это исправить?
Ответы:
java <class-name>
Синтаксис командыПрежде всего вам необходимо понять, как правильно запустить программу с помощью команды java
(или javaw
).
Обычный синтаксис 1 таков:
java [ <options> ] <class-name> [<arg> ...]
где <option>
- параметр командной строки (начинающийся с символа «-»), <class-name>
полное имя класса Java и <arg>
произвольный аргумент командной строки, который передается вашему приложению.
1 - Есть некоторые другие синтаксисы, которые описаны в конце этого ответа.
Полное имя (FQN) для класса обычно пишется так же, как в исходном коде Java; например
packagename.packagename2.packagename3.ClassName
Однако некоторые версии java
команды позволяют использовать косые черты вместо точек; например
packagename/packagename2/packagename3/ClassName
который (сбивает с толку) выглядит как путь к файлу, но не один. Обратите внимание, что термин полностью определенное имя - это стандартная терминология Java ... я не просто придумал, чтобы сбить вас с толку :-)
Вот пример того, как java
должна выглядеть команда:
java -Xmx100m com.acme.example.ListUsers fred joe bert
Вышеуказанное заставит java
команду сделать следующее:
com.acme.example.ListUsers
класса.main
метод с сигнатурой , типом возвращаемого значения и модификаторами, заданными в public static void main(String[])
. (Обратите внимание, что имя аргумента метода НЕ является частью подписи.)String[]
.Когда вы получаете сообщение «Не удалось найти или загрузить основной класс ...», это означает, что первый шаг не выполнен. java
Команда не смогла найти класс. И действительно, «...» в сообщении будет полным именем класса, который java
ищет.
Так почему же он не может найти класс?
Первой вероятной причиной является то, что вы, возможно, указали неправильное имя класса. (Или ... правильное имя класса, но в неправильной форме.) Рассматривая приведенный выше пример, можно привести множество неправильных способов указания имени класса:
Пример № 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 11 или новее; см. Ниже)
java ListUser.java
Пример №6 - вы полностью забыли имя класса
java lots of arguments
Вторая вероятная причина - правильное имя класса, но java
команда не может найти класс. Чтобы понять это, вам необходимо понять понятие «classpath». Это хорошо объясняется документацией Oracle:
java
Документация командыИтак ... если вы правильно указали имя класса, то следует проверить, правильно ли вы указали путь к классам:
java
команды. Проверьте правильность имен каталогов и файлов JAR.java
команды.;
в Windows и :
других. Если вы используете неправильный разделитель для вашей платформы, вы не получите явного сообщения об ошибке. Вместо этого вы получите несуществующий файл или каталог по пути, который будет игнорироваться .)Когда вы помещаете каталог в 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 не сможет найти класс.
Если ваши классы 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
и так далее.Путь к классам должен включать все другие (не системные) классы, от которых зависит ваше приложение. (Системные классы располагаются автоматически, и вам редко нужно беспокоиться об этом.) Для корректной загрузки основного класса JVM должна найти:
(Примечание: спецификации JLS и JVM позволяют некоторой области для JVM загружать классы «лениво», и это может повлиять, когда выдается исключение загрузчика классов.)
Иногда случается, что кто-то помещает файл исходного кода в неправильную папку в их дереве исходного кода, или они пропускают package
объявление. Если вы сделаете это в IDE, компилятор IDE немедленно сообщит вам об этом. Точно так же, если вы используете достойный инструмент сборки Java, инструмент будет работать javac
таким образом, чтобы обнаружить проблему. Однако, если вы создаете свой Java-код вручную, вы можете сделать это таким образом, чтобы компилятор не заметил проблемы, и полученный файл «.class» оказался не там, где вы ожидаете.
Там много чего можно проверить, и что-то легко пропустить. Попробуйте добавить -Xdiag
опцию в java
командную строку (как первое после java
). Он будет выводить различные вещи о загрузке классов, и это может дать вам подсказки о том, какова реальная проблема.
Также рассмотрите возможные проблемы, вызванные копированием и вставкой невидимых или не-ASCII символов с веб-сайтов, документов и так далее. И рассмотрим «гомоглифы», если две буквы или символы выглядят одинаково ... но это не так.
Наконец, вы, очевидно, можете столкнуться с этой проблемой, если попытаетесь запустить файл JAR с неверными сигнатурами в (META-INF/*.SF)
.
java
Существует три альтернативных синтаксиса для запуска программ Java с использованием java command
.
1) Синтаксис, используемый для запуска «исполняемого» файла JAR, выглядит следующим образом:
java [ <options> ] -jar <jar-file-name> [<arg> ...]
например
java -Xmx100m -jar /usr/local/acme-example/listuser.jar fred
Имя класса точки входа (то есть com.acme.example.ListUser
) и путь к классу указываются в МАНИФЕСТЕ файла JAR.
2) Синтаксис для запуска приложения из модуля (Java 9 и выше) выглядит следующим образом:
java [ <options> ] --module <module>[/<mainclass>] [<arg> ...]
Имя класса точки входа либо определяется самим <module>
собой, либо задается необязательным <mainclass>
.
3) Начиная с Java 11, вы можете скомпилировать и запустить один файл исходного кода и запустить его со следующим синтаксисом:
java [ <options> ] <sourcefile> [<arg> ...]
где (обычно) файл с суффиксом ".java".
Для получения более подробной информации, пожалуйста, обратитесь к официальной документации для java
команды для выпуска Java, который вы используете.
Типичная Java IDE поддерживает запуск приложений Java в самой IDE JVM или в дочерней JVM. Как правило, они защищены от этого конкретного исключения, поскольку в среде IDE используются собственные механизмы для создания пути к классам среды выполнения, определения основного класса и создания java
командной строки.
Однако это исключение по-прежнему возможно, если вы делаете что-то за спиной IDE. Например, если вы ранее настроили Application Launcher для своего приложения Java в Eclipse, а затем переместили файл JAR, содержащий класс «main», в другое место в файловой системе, не сообщая Eclipse , Eclipse невольно запустит JVM с неправильным путем к классу.
Короче говоря, если вы столкнулись с этой проблемой в IDE, проверьте наличие таких вещей, как устаревшее состояние IDE, неработающие ссылки на проекты или неработающие конфигурации запуска.
Для IDE также возможно просто запутаться. IDE - это чрезвычайно сложные части программного обеспечения, состоящие из множества взаимодействующих частей. Многие из этих частей применяют различные стратегии кэширования, чтобы сделать среду IDE в целом отзывчивой. Иногда они могут пойти не так, и одним из возможных симптомов являются проблемы при запуске приложений. Если вы подозреваете, что это может произойти, стоит попробовать другие вещи, такие как перезапуск вашей IDE, перестройка проекта и так далее.
java -cp ../third-party-library.jar com.my.package.MyClass
:; это не работает, вместо этого необходимо также добавить локальную папку в путь к классу (разделенный :
, как это:, java -cp ../third-party-library.jar:. com.my.package.MyClass
тогда это должно работать
java
это не говорит о том, что он не находит импортированный класс, но вместо этого основной класс, который вы пытаетесь запустить. Это вводит в заблуждение, хотя я уверен, что есть причина для этого. У меня был случай, когда я java
точно знал, где находится мой класс, однако он не смог найти один из импортированных классов. Вместо этого он пожаловался на то, что не нашел своего основного класса. Действительно, раздражает.
Если ваше имя исходного кода HelloWorld.java, ваш скомпилированный код будет HelloWorld.class
.
Вы получите эту ошибку, если позвоните с помощью:
java HelloWorld.class
Вместо этого используйте это:
java HelloWorld
javac TestCode.java
затемjava TestCode
java -classpath . HelloWorld
Если ваши классы находятся в пакетах, вам нужно перейти cd
в корневой каталог вашего проекта и запустить его, используя полное имя класса (packageName.MainClassName).
Пример:
Мои занятия здесь:
D:\project\com\cse\
Полное имя моего основного класса:
com.cse.Main
Итак, я cd
вернулся в корневую директорию проекта:
D:\project
Затем выполните java
команду:
java com.cse.Main
Этот ответ предназначен для спасения начинающих Java-программистов от разочарования, вызванного распространенной ошибкой. Я рекомендую вам прочитать принятый ответ для более глубоких знаний о пути к классам Java.
Если вы определили главный класс и метод main в apackage
, вы должны запустить его в иерархическом каталоге, используя полное имя класса ( 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
.
Когда один и тот же код работает на одном ПК, но на другом показывает ошибку, лучшее решение, которое я когда-либо нашел, - это компилировать, как показано ниже:
javac HelloWorld.java
java -cp . HelloWorld
javac -classpath . HelloWorld.java
бы сработало! И это лучшее решение в вашем случае.
Что помогло мне, так это указать classpath в командной строке, например:
Создать новую папку, 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!
java
не смотрел на $ CLASSPATH (потому что вы использовали -classpath или -jar) или 2) параметр classpath не был установлен в среде, которая не действовала в контексте, который java
был запустить; например, потому что вы не «источник» файла, где добавлены команды setenv в правой оболочке.
Согласно сообщению об ошибке («Не удалось найти или загрузить основной класс»), существуют две категории проблем:
Основной класс не может быть найден, если в полностью определенном имени класса присутствует опечатка или неправильный синтаксис или он не существует в указанном пути к классам .
Главный класс не может быть загружен, когда класс не может быть инициирован , обычно основной класс расширяет другой класс, и этот класс не существует в предоставленном пути к классам.
Например:
public class YourMain extends org.apache.camel.spring.Main
Если верблюжья пружина не включена, об этой ошибке будет сообщено.
extends
). Я только что узнал, что когда основной класс не загружается из-за расширения другого, который не может быть найден , java не сообщает, какой именно класс не был найден (в отличие от этого NoClassDefFoundError
). Так что да, это случается, и это невероятная ситуация, когда вы этого не знаете.
У меня была такая ошибка в этом случае:
java -cp lib.jar com.mypackage.Main
Работает с ;
Windows и :
Unix:
java -cp lib.jar; com.mypackage.Main
Main
не в файле JAR. -cp lib.jar;
означает то же самое, что -cp lib.jar;.
и текущий каталог включен в путь к классам.
Попробуйте -Xdiag .
Ответ Стива С. хорошо описывает возможные случаи, но иногда определить, не удается ли найти класс или загрузить его, может быть не так просто. Используйте java -Xdiag
(начиная с JDK 7). Это распечатывает красивую трассировку стека, которая дает подсказку о том, что Could not find or load main class
означает сообщение.
Например, он может указать вам на другие классы, используемые основным классом, которые не могут быть найдены, и помешал загрузке основного класса.
Используйте эту команду:
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.
-cp .
это не нужно, потому что если $CLASSPATH
не установлено, то .
это путь к классу по умолчанию.
echo %CLASSPATH%
выводит?) И нет, я не могу проверить, потому что у меня нет ПК с Windows.
Иногда то, что может быть причиной проблемы, не имеет ничего общего с основным классом, и мне пришлось найти это трудным путем. Это была ссылочная библиотека, которую я переместил, и она дала мне:
Не удалось найти или загрузить основной класс ххх Linux
Я просто удалил эту ссылку, добавил ее снова, и она снова заработала.
В этом случае у вас есть:
Не удалось найти или загрузить основной класс ?
Это потому, что вы используете "-classpath", но тире - это не та тире, которая используется java
в командной строке. У меня была эта проблема копирования и вставки из блокнота в cmd.
У меня была та же проблема, и в конце концов я нашел свою ошибку :) Я использовал эту команду для компиляции, и она работала правильно:
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
Это может помочь вам, если ваш случай особенно похож на мой: как новичок я столкнулся с этой проблемой, когда пытался запустить программу на Java.
Я скомпилировал это так:
javac HelloWorld.java
И я попытался запустить также с тем же расширением:
java Helloworld.java
Когда я удалил .java
и переписал команду как java HelloWorld
, программа работала отлично. :)
Все ответы здесь, похоже, направлены на пользователей Windows. Для Mac разделитель пути к классам - :
нет ;
. Так как при установке ошибки путь к классу ;
не генерируется, это может быть трудно обнаружить при переходе с Windows на Mac.
Вот соответствующая команда Mac:
java -classpath ".:./lib/*" com.test.MyClass
Где в этом примере пакет com.test
и lib
папка также должны быть включены в classpath.
/*
это нужно?
Расположение файла класса: C: \ test \ com \ company
Имя файла: Main.class
Полностью определенное имя класса: com.company.Main
Команда командной строки:
java -classpath "C:\test" com.company.Main
Обратите внимание, что путь к классу НЕ включает \ com \ company
Я потратил приличное количество времени, пытаясь решить эту проблему. Я думал, что каким-то образом неправильно устанавливал свой путь к классу, но проблема заключалась в том, что я набрал:
java -cp C:/java/MyClasses C:/java/MyClasses/utilities/myapp/Cool
вместо:
java -cp C:/java/MyClasses utilities/myapp/Cool
Я думал, что значение «полный» означает включение полного пути вместо полного имени пакета.
utilities.myapp.Cool
или как его имя пакета, если таковое имеется.
Сначала установите путь с помощью этой команды;
set path="paste the set path address"
Затем вам нужно загрузить программу. Введите «cd (имя папки)» на сохраненный диск и скомпилируйте его. Например, если моя программа хранится на диске D, введите «D:», нажмите enter и введите «cd (имя папки)».
if "cd" helps then it by luck rather than by judgement
, Это неправильно (я полагаю), поскольку java использует текущий каталог .
как часть пути к классам по умолчанию.
Что исправило проблему в моем случае:
Щелкните правой кнопкой мыши проект / класс, который вы хотите запустить, затем Run As
-> Run Configurations
. Затем вы должны либо исправить существующую конфигурацию, либо добавить новую следующим образом:
откройте Classpath
вкладку, нажмите на Advanced...
кнопку, затем добавьте bin
папку вашего проекта.
Если вы используете 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>
Это особый случай, но поскольку я пришел на эту страницу в поисках решения и не нашел его, я добавлю его сюда.
Windows (протестировано с 7) не принимает специальные символы (например, á
) в именах классов и пакетов. Linux делает, хотя.
Я узнал об этом, когда построил .jar
в NetBeans и попытался запустить его в командной строке. Он работал в NetBeans, но не в командной строке.
В Windows .;
укажите значение CLASSPATH в начале.
. (точка) означает «смотреть в текущем каталоге». Это постоянное решение.
Также вы можете установить его «один раз» с помощью набора CLASSPATH=%CLASSPATH%;.
. Это будет продолжаться до тех пор, пока ваше окно cmd открыто.
Вам действительно нужно сделать это из 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
cd
в src
и затем запустить команду, java ../bin com.blah.blah.MyClass
которая работала для меня. Так что спасибо за совет!
В 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/
При запуске 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.
Я также сталкивался с подобными ошибками при тестировании соединения JDBC Java MongoDB. Я думаю, что было бы хорошо кратко изложить мое окончательное решение, чтобы в будущем кто-нибудь мог непосредственно изучить две команды и хорошо продолжить.
Предположим, вы находитесь в каталоге, где существуют ваш файл Java и внешние зависимости (файлы JAR).
Обобщение:
javac -cp mongo-java-driver-3.4.1.jar JavaMongoDBConnection.java
Запустить:
java -cp mongo-java-driver-3.4.1.jar: JavaMongoDBConnection
JavaMongoDBConnection
не имеет пакета и 2) вы не меняете каталог. Это, по меньшей мере, хрупко. И не объясняя проблемы, это заставит новичков попробовать этот подход в ситуациях, когда он не будет работать . Короче говоря, он поощряет «методы программирования вуду»: en.wikipedia.org/wiki/Voodoo_programming
Хорошо, ответов уже много, но никто не упомянул случай, когда права доступа к файлам могут быть причиной.
Во время работы пользователь может не иметь доступа к файлу 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.
Я получил эту ошибку после выполнения mvn eclipse:eclipse
этого .classpath
Немного испортил мой файл.
Пришлось изменить строки .classpath
из
<classpathentry kind="src" path="src/main/java" including="**/*.java"/>
<classpathentry kind="src" path="src/main/resources" excluding="**/*.java"/>
в
<classpathentry kind="src" path="src/main/java" output="target/classes" />
<classpathentry kind="src" path="src/main/resources" excluding="**" output="target/classes" />
Я не смог решить эту проблему с помощью решений, изложенных здесь (хотя указанный ответ, несомненно, очистил мои концепции). Я сталкивался с этой проблемой два раза и каждый раз пробовал разные решения (в Eclipse IDE).
main
методами в разных классах моего проекта. Итак, я удалил main
метод из последующих классов.main
методов не решит проблему. Технически нет ничего плохого в приложении с несколькими точками входа.