Какво означава "Could not find or load main class"?

Често срещан проблем при новите разработчици на Java е, че програмите им не се изпълняват със съобщение за грешка: не може да намери или зареди главния клас ...`

Какво означава това, какво го причинява и как да го отстраните?

Решение

Синтаксис на командата java

Преди всичко трябва да разберете правилния начин за стартиране на програма с помощта на командата java (или javaw). Нормалният синтаксис1 е следният:

    java [  ... ]  [ ...]

където е опция от командния ред (започваща със символа "-"), е напълно квалифицирано име на Java клас, а `` е произволен аргумент от командния ред, който се предава на вашето приложение.
1 - Съществува втори синтаксис за "изпълними" JAR файлове, който ще опиша по-надолу. Напълно квалифицираното име (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 не може да намери класа

    Когато получите съобщението "Could not find or load main class ...", това означава, че първата стъпка е неуспешна. Командата java не е успяла да намери класа. И наистина, "..." в съобщението ще бъде пълно квалифицираното име на класа, което java търси. Тогава защо тя не може да намери класа?
    Причина № 1 - допуснали сте грешка с аргумента classname

    Първата вероятна причина е, че може да сте предоставили грешно име на клас. (Или ... правилното име на клас, но в неправилна форма.) Като се има предвид горният пример, ето различни неправилни начини за задаване на името на класа:

  • Пример № 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 много аргументи Причина № 2 - некоректно е посочен classpath на приложението

    Втората вероятна причина е, че името на класа е правилно, но командата java не може да намери класа. За да разберете това, трябва да разберете концепцията за "classpath". Това е обяснено добре в документацията на Oracle:

  • Документацията на командата java

  • Задаване на пътя на класа.

  • Учебникът по Java - PATH и CLASSPATH И така... ако сте посочили правилно името на класа, следващото нещо, което трябва да проверите, е дали сте посочили правилно classpath:

  1. Прочетете трите документа, към които са дадени връзки по-горе. (Да ... ПРОЧЕТЕТЕ ги. Важно е програмистът на Java да разбира поне основите на работата на механизмите на Java classpath).
  2. Погледнете командния ред и/или променливата на средата CLASSPATH, която е в сила, когато изпълнявате командата java. Проверете дали имената на директориите и имената на JAR файловете са правилни.
  3. Ако има релативни имена на пътища в classpath, проверете дали те се разрешават правилно ... от текущата директория, която е в сила, когато изпълнявате командата java.
  4. Проверете дали класът (споменат в съобщението за грешка) може да бъде намерен в ефективния classpath.
  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" на classpath, тогава JVM нямаше да може да намери класа. Причина #2б - пътят до поддиректорията не съвпада с FQN

Ако FQN на вашите класове е com.acme.example.Foon, тогава JVM ще търси "Foon.class" в директорията "com/acme/example":

  • Ако структурата на директориите ви не съответства на именуването на пакетите според горния модел, JVM няма да намери вашия клас.
  • Ако се опитате да преименувате клас, като го преместите, това също няма да се получи ... но следата на изключението ще бъде различна. Тя може да се изразява в следното: Причинено от: java.lang.NoClassDefFoundError: <path> (грешно име: ) тъй като 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 и т.н.

  • Мислете внимателно, когато избирате между абсолютни и относителни имена на пътища в 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 файлове, е следният:

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

напр.

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

В този случай името на класа на входната точка (т.е. 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 и да възстановите проекта.

Други препратки

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

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

Не можа да намери или зареди главния клас xxx Linux

Просто изтрих тази препратка, добавих я отново и всичко отново работи добре.

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

Първо задайте пътя, като използвате тази команда;

set path="paste the set path address"

След това трябва да заредите програмата. Въведете "cd (име на папка)" в съхраненото устройство и я компилирайте. Например, ако моята програма е съхранена на устройството D, въведете "D:" натиснете Enter и въведете " cd (име на папка)".

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