Какво означава "Could not find or load main class"?
Често срещан проблем при новите разработчици на Java е, че програмите им не се изпълняват със съобщение за грешка: не може да намери или зареди главния клас ...`
Какво означава това, какво го причинява и как да го отстраните?
1270
3
Синтаксис на командата
java
Преди всичко трябва да разберете правилния начин за стартиране на програма с помощта на командата
java
(илиjavaw
). Нормалният синтаксис1 е следният:където
е опция от командния ред (започваща със символа "-"),
е напълно квалифицирано име на Java клас, а `` е произволен аргумент от командния ред, който се предава на вашето приложение.1 - Съществува втори синтаксис за "изпълними" JAR файлове, който ще опиша по-надолу. Напълно квалифицираното име (FQN) за класа се записва условно, както в изходния код на Java; напр.
Въпреки това някои версии на командата
java
позволяват да се използват наклонени черти вместо точки; напр.което (объркващо) изглежда като име на файл, но не е такова. Обърнете внимание, че терминът пълно квалифицирано име е стандартна терминология на Java ... а не нещо, което съм измислил, за да ви объркам :-) Ето един пример за това как трябва да изглежда една команда
java
:Горното ще накара командата
java
да направи следното:com.acme.example.ListUsers
.main
с знак, тип на връщане и модификатори, зададени отpublic static void main(String[])
. (Обърнете внимание, че името на аргумента на метода не е част от сигнатурата.)Извикайте този метод, като му предадете аргументите от командния ред ("fred", "joe", "bert") като
String[]
. Причини, поради които Java не може да намери класаКогато получите съобщението "Could not find or load main class ...", това означава, че първата стъпка е неуспешна. Командата
java
не е успяла да намери класа. И наистина, "..." в съобщението ще бъде пълно квалифицираното име на класа, коетоjava
търси. Тогава защо тя не може да намери класа?Причина № 1 - допуснали сте грешка с аргумента classname
Първата вероятна причина е, че може да сте предоставили грешно име на клас. (Или ... правилното име на клас, но в неправилна форма.) Като се има предвид горният пример, ето различни неправилни начини за задаване на името на класа:
Пример № 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 - забравили сте изцяло името на класа java много аргументи Причина № 2 - некоректно е посочен classpath на приложението
Втората вероятна причина е, че името на класа е правилно, но командата
java
не може да намери класа. За да разберете това, трябва да разберете концепцията за "classpath". Това е обяснено добре в документацията на Oracle:Документацията на командата
java
Задаване на пътя на класа.
Учебникът по Java - PATH и CLASSPATH И така... ако сте посочили правилно името на класа, следващото нещо, което трябва да проверите, е дали сте посочили правилно classpath:
java
. Проверете дали имената на директориите и имената на JAR файловете са правилни.java
.Обърнете внимание, че синтаксисът на 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" на classpath, тогава JVM нямаше да може да намери класа. Причина #2б - пътят до поддиректорията не съвпада с FQN
Ако FQN на вашите класове е
com.acme.example.Foon
, тогава JVM ще търси "Foon.class" в директорията "com/acme/example":com.acme.example.Foon
,/usr/local/acme/classes/com/acme/example/Foon.class
,/usr/local/acme/classes/com/acme/example/
, тогава:Бележки:
Опцията
-classpath
може да бъде съкратена до-cp
в повечето версии на Java. Проверете съответните записи в ръководството заjava
,javac
и т.н.Мислете внимателно, когато избирате между абсолютни и относителни имена на пътища в classpaths. Не забравяйте, че относителното име на пътя може да се "прекъсне", ако текущата директория се промени.
Причина #2c - липсващи зависимости в classpath
Пътят на класа трябва да включва всички други (несистемни) класове, от които зависи вашето приложение. (Системните класове се намират автоматично и рядко се налага да се занимавате с това). За да се зареди правилно главният клас, JVM трябва да намери:
самия клас.
всички класове и интерфейси в йерархията на суперкласовете (например вижте https://stackoverflow.com/questions/42880748)
всички класове и интерфейси, към които се препраща чрез декларации на променливи или променливи, или чрез изрази за извикване на метод или за достъп до поле. (Забележка: спецификациите на JLS и JVM позволяват на JVM да зарежда класове "мързеливо" и това може да повлияе на това кога се хвърля изключение от classloader). Причина № 3 - класът е деклариран в грешен пакет
Понякога се случва някой да постави файл с изходен код в грешната папка в дървото на изходния код или пропуска декларацията за
пакет
. Ако направите това в някоя IDE, компилаторът на IDE'та веднага ще ви съобщи за това. По същия начин, ако използвате приличен инструмент за изграждане на Java, инструментът ще изпълниjavac
по начин, който ще открие проблема. Ако обаче изграждате кода си на Java на ръка, можете да го направите по такъв начин, че компилаторът да не забележи проблема и полученият файл ".class" да не е на мястото, на което очаквате да бъде. Все още не можете да откриете проблема?Има много неща, които трябва да се проверят, и е лесно да се пропусне нещо. Опитайте да добавите опцията
-Xdiag
към командния редjava
(като първото нещо следjava
). Тя ще изведе различни неща за зареждането на класовете и това може да ви подскаже какъв е истинският проблем. Също така помислете за възможни проблеми, причинени от копиране и поставяне на невидими или неASCII символи от уебсайтове, документи и т.н. И помислете за "хомоглифите", когато две букви или символи изглеждат еднакво... но не са.Синтаксисът
java -jar
Алтернативният синтаксис, използван за "изпълними" JAR файлове, е следният:
напр.
В този случай името на класа на входната точка (т.е.
com.acme.example.ListUser
) и пътя на класа са посочени в MANIFEST на JAR файла.IDEs
Типичната IDE на Java има поддръжка за стартиране на Java приложения в самата JVM на IDE или в дъщерна JVM. Те са общо имунизирани срещу това конкретно изключение, тъй като IDE използва свои собствени механизми за конструиране на classpath за изпълнение, идентифициране на главния клас и създаване на командния ред
java
. Въпреки това е възможно това изключение да се появи, ако правите нещо зад гърба на IDE. Например, ако преди това сте настроили Application Launcher за вашето Java приложение в Eclipse и след това сте преместили JAR файла, съдържащ класа "main", на друго място във файловата система без да кажете на Eclipse, Eclipse несъзнателно ще стартира JVM с неправилен classpath. Накратко, ако получите този проблем в IDE, проверете за неща като застояло състояние на IDE, нарушени препратки към проекта или нарушени конфигурации на стартиращите устройства. Възможно е също така IDE просто да се обърка. IDE's са изключително сложни части от софтуера, които се състоят от много взаимодействащи си части. Много от тези части използват различни стратегии за кеширане, за да направят IDE като цяло гъвкава. Понякога те могат да се объркат и един от възможните симптоми са проблеми при стартирането на приложенията. Ако подозирате, че това може да се случи, струва си да опитате да рестартирате IDE и да възстановите проекта.Други препратки
Понякога това, което може да е причина за проблема, няма нищо общо с главния клас, а на мен ми се наложи да разбера това по трудния начин. Беше препратена библиотека, която преместих, и тя ми даде:
Не можа да намери или зареди главния клас xxx Linux
Просто изтрих тази препратка, добавих я отново и всичко отново работи добре.
Първо задайте пътя, като използвате тази команда;
След това трябва да заредите програмата. Въведете "cd (име на папка)" в съхраненото устройство и я компилирайте. Например, ако моята програма е съхранена на устройството D, въведете "D:" натиснете Enter и въведете " cd (име на папка)".