Що означає "Не вдалося знайти або завантажити основний клас"?


1370

Поширена проблема, з якою стикаються нові розробники Java, полягає в тому, що їхні програми не працюють із повідомленням про помилку: Could not find or load main class ...

Що це означає, що це викликає, і як ви повинні це виправити?


37
Зауважте, що це питання "самовідповіді", яке має бути загальним контрольним запитом для нових користувачів Java. Я не зміг знайти існуючих запитань, які б адекватно висвітлювали це (ІМО).
Стівен C

Відповіді:


1230

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команда виконає наступне:

  1. Пошук складеної версії com.acme.example.ListUsersкласу.
  2. Завантажте клас.
  3. Перевірте, чи в класі є mainметод з підписом , типом повернення та модифікаторами, заданими public static void main(String[]). (Зверніть увагу, ім'я аргументу методу НЕ є частиною підпису.)
  4. Викликайте цей метод, передаючи йому аргументи командного рядка ("fred", "joe", "bert") як String[].

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

Коли ви отримуєте повідомлення "Не вдалося знайти або завантажити основний клас ...", це означає, що перший крок не вдався. 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 11 або новішої версії; див. Нижче)

    java ListUser.java
  • Приклад №6 - ви повністю забули ім'я класу

    java lots of arguments

Причина №2 - класний шлях програми не вказаний неправильно

Друга ймовірна причина полягає в тому, що ім'я класу правильне, але що javaкоманда не може знайти клас. Щоб зрозуміти це, потрібно зрозуміти поняття "класової". Це добре пояснюється документацією Oracle:

Отже ... якщо ви правильно вказали ім'я класу, наступне, що потрібно перевірити, це те, що ви вказали класний шлях правильно:

  1. Прочитайте три зв'язані вище документи. (Так ... ЧИТАТИ їх! Важливо, щоб програміст Java розумів принаймні основи роботи механізмів Java classpath.)
  2. Подивіться на командний рядок та / або змінну середовища CLASSPATH, яка діє під час виконання javaкоманди. Перевірте правильність імен каталогів та імен файлів JAR.
  3. Якщо в класі class є відносні імена шляхів, перевірте, чи правильно вони розв’язані ... з поточного каталогу, який діє під час виконання javaкоманди.
  4. Переконайтесь, що клас (згаданий у повідомленні про помилку) може бути розташований на ефективному класі.
  5. Зауважте, що синтаксис classpath відрізняється для Windows порівняно з Linux та Mac OS. (Розділювач класових маршрутів є ;в Windows та :інших. Якщо ви використовуєте неправильний роздільник для своєї платформи, ви не отримаєте явного повідомлення про помилку. Натомість ви отримаєте неіснуючий файл або каталог на шляху, який буде мовчазно ігноруватися. .)

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

Коли ви кладете каталог на classpath, він умовно відповідає кореню простору імен кваліфікованих. Класи розташовані в структурі каталогів під цим коренем, шляхом зіставлення повністю кваліфікованого імені до імені шляху . Наприклад, якщо "/ usr / local / acme / class" знаходиться на шляху до класу, тоді, коли JVM шукає клас, який називається com.acme.example.Foon, він буде шукати файл ".class" з таким ім'ям шляху:

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

Якби ви поставили "/ usr / local / acme / class / com / acme / example" на classpath, то 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і так далі.
  • Ретельно подумайте, обираючи між абсолютними та відносними іменами шляхів у класі. Пам'ятайте, що відносне ім'я шляху може "зламатися", якщо зміниться поточний каталог.

Причина №2с - залежності, відсутні у класового шляху

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

(Примітка: специфікації JLS та JVM дозволяють деякому простору для JVM завантажувати класи "ліниво", і це може вплинути на викид винятку завантажувача класів.)

Причина №3 - клас оголошено неправильним пакетом

Іноді трапляється, що хтось ставить файл вихідного коду в неправильну папку у своєму дереві вихідного коду, або вони залишають 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. Наприклад, якщо ви раніше встановили запуск програми для свого додатка Java в Eclipse, а потім перенесли файл JAR, що містить "головний" клас, в інше місце у файловій системі, не повідомляючи Eclipse , Eclipse мимоволі запустить JVM з неправильним класовим шляхом.

Якщо коротко, якщо ви отримаєте цю проблему в IDE, перевірте, чи немає таких речей, як несвіжий стан IDE, пошкоджені посилання на проект чи зламані конфігурації запуску.

Також можна IDE просто плутати. IDE - це надзвичайно складні програми, що містять багато взаємодіючих частин. Багато з цих частин застосовують різні стратегії кешування, щоб зробити IDE в цілому чуйним. Вони іноді можуть піти не так, і одним із можливих симптомів є проблеми під час запуску програм. Якщо ви підозрюєте, що це може статися, варто спробувати інші речі, такі як перезапуск IDE, відновлення проекту тощо.


Інші посилання


43
У мене була ця проблема, коли я намагався запустити Клас із бібліотекою сторонніх організацій. Я викликається Java так: java -cp ../third-party-library.jar com.my.package.MyClass; це не працює, замість цього потрібно додати локальну папку до шляху до класу (відокремлено :, як це:, java -cp ../third-party-library.jar:. com.my.package.MyClassтоді воно має працювати
lanoxx

22
Після років програмування java мені все ж вдалося опинитися на цій сторінці. Для мене проблема полягала в тому, що синтаксис classpath залежить від ОС . Я начебто новачка в програмуванні в Windows і поняття не мала.
клавішник

5
Додаткові замітки, пункт 2 врятуйте мене! Сумно бачити, що javaне сказано, що він не знаходить імпортований клас, а натомість основний клас, який ви намагаєтеся запустити. Це вводить в оману, хоча я впевнений, що в цьому є причина. У мене був випадок, коли javaточно знали, де знаходиться мій клас, проте він не міг знайти жодного із імпортованих класів. Замість того, щоб сказати, він скаржився на те, що не знайшов свого основного класу. Дійсно, дратує.
MSX

Я мав цю проблему двічі в Eclipse. Перший раз підпис main () був неправильним. Вдруге я перейменував. Мені довелося видалити .jar файл з Project> Properties> Java Build Path> Libraries.
GregT

Я зіткнувся з цим втретє. Я запустив програму з пакетного файлу Windows 10 і поставив ім'я .jar у змінну (називається "-cp% jarname%; lib *"). Я помилково поставив додатковий пробіл в кінці jarname, і це спричинило помилку. Хет-трюк :)
GregT

239

Якщо ваш вихідний код ім'я HelloWorld.java, ваш компільований код буде HelloWorld.class.

Ви отримаєте цю помилку, якщо ви будете називати її за допомогою:

java HelloWorld.class

Замість цього скористайтеся цим:

java HelloWorld

3
Проблема полягає в тому, що це рішення працює лише для класів Java, оголошених у пакеті за замовчуванням, без залежностей від файлів JAR. (І навіть тоді, не весь час.) Більшість програм Java не такі прості.
Стівен C

1
як сказав Стівен, це працює лише з "пакетом за замовчуванням" - що означає відсутність декларації пакета у верхній частині файлу. Для швидкого випробування якогось коду я зробив: javac TestCode.javaза нимjava TestCode
Хтось десь

Це для мене не вийшло. У ньому все ще написано: "Не вдалося знайти або завантажити основний клас HelloWorld"
Джим

java -jar HelloWorld.jar - також варіант
BMaximus

12
Мені потрібно було це зробитиjava -classpath . HelloWorld
Кріс Принс

136

Якщо ваші класи містяться в пакетах, вам доведеться перейти cdдо кореневого каталогу вашого проекту та запустити, використовуючи повністю кваліфіковане ім’я класу (packageName.MainClassName).

Приклад:

Мої заняття тут:

D:\project\com\cse\

Повноцінне ім’я мого основного класу:

com.cse.Main

Тому я cdповертаюся до кореневого каталогу проекту:

D:\project

Потім видайте javaкоманду:

java com.cse.Main

Ця відповідь призначена для того, щоб врятувати початківців програмістів Java від розчарування, спричиненого поширеною помилкою, я рекомендую вам прочитати прийняту відповідь, щоб отримати більш глибокі знання про клас Java.


2
Ця відповідь складає цілий набір припущень. І є інші способи досягти цього. Замість того, щоб сліпо дотримуватися вищевказаних порад, я б рекомендував людям витрачати час, щоб прочитати посилання в моєму відповіді, які пояснюють, як працює класний шлях Java. Краще ЗНАЙТИ, що ти робиш ...
Stephen C

2
Ця відповідь робить точні припущення, що мені було потрібно :) Я знаходився в каталозі .class-файлу, і java.exe не працював. Після того, як я cd-ed був вище і запустив з ім'ям пакета, включеним у командний рядок, він працював.
Нік Костянтин

61

Якщо ви визначаєте головний клас та основний метод у 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.


1
Див. "Додаткові примітки №1" моєї відповіді. Для кращого пояснення цієї проблеми.
Стівен C

14
@StephenC Так, ваша відповідь є більш повною (і, звичайно, +1), але саме ця відповідь мала в ній слово "пакет", що дозволило мені швидко знайти те, що мені потрібно. І це спрацювало. Так +1 Разаві. StephenC, вашому не вистачає простого прикладу пакета, який мені потрібен, оскільки я новачок у Java.
кморт

5
Це була саме моя проблема. Я перебираю тони Java doc, і цей конкретний приклад - те, що мені потрібно
Джон

1
Так, конкретний приклад хороший, це спрацювало чудово. Я впевнений, що головна відповідь дуже ґрунтовна, але дерево було важко побачити за лісом. Хороший @Razavi
Піксель

1
Мені подобається ця коротша і корисна відповідь замість прийнятої!
Спара

46

Коли той самий код працює на одному ПК, але він показує помилку в іншому, найкращим рішенням, який я коли-небудь знайшов, є компілювання, як наступне:

javac HelloWorld.java
java -cp . HelloWorld

2
Це не є хорошою рекомендацією. Ви залежаєте від того, що змінна середовища CLASSPATH не налаштована або маєте значення, яке відповідає ".". Так, це працює у багатьох випадках, але в інших не буде.
Стівен C

Ну звичайно javac -classpath . HelloWorld.javaпрацював би! І це краще рішення у вашому випадку.
Стівен C

2
Якщо у вас є "пакунок com.some.address" в якості першого рядка - це не буде працювати. Вам потрібно буде прокоментувати 'адресу пакета' ..
Джо,

1
@Joe - Цей злом (коментуючи пакет) спрацює (в деяких випадках), але це погана ідея. Краща ідея - дізнатися / зрозуміти, що спричинило проблему, та застосувати правильне рішення.
Стівен C

36

Що допомогло мені, було вказати класний шлях у командному рядку, наприклад:

  1. Створіть нову папку, C:\temp

  2. Створіть файл Temp.java в C:\temp, із таким класом:

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

    javac Temp.java
  4. Запустіть компільований клас Java, додавши -classpathможливість повідомити JRE, де знайти клас:

    java -classpath C:\temp Temp Hello!

3
В Ubuntu мені також довелося вказати шлях. Не розумійте, чому він не може використовувати Поточний робочий каталог за замовчуванням. Я переконаний, що Java спонсорується виробниками клавіатур !!
пішов

1
@gone - причина, що "." за замовчуванням не в $ PATH - це пастка безпеки. seas.upenn.edu/cets/answers/dot-path.html
Стівен C

Дякую за це ...... хоча навіть не впевнений, чому java не змогла знайти класний шлях навіть після встановлення його у змінних оточення.
akash89

@ akash89 - Найімовірнішими причинами були: 1) javaне дивився на $ CLASSPATH (тому що ти використовував -classpath або -jar) або 2) параметр classpath не був встановлений у середовищі, що не діяло в контексті, що javaбув бігати; наприклад, тому що ви не "джерело" файлу, де додано команди setenv у правій оболонці.
Стівен С

У мене все ще помилка: Не вдалося знайти або завантажити основний клас Temp хто-небудь може допомогти!
Зірка

27

Відповідно до повідомлення про помилку ("Не вдалося знайти або завантажити основний клас"), існує дві категорії проблем:

  1. Основного класу не вдалося знайти
  2. Не вдалося завантажити основний клас (ця справа не повністю обговорюється у прийнятій відповіді)

Неможливо знайти основний клас, коли в повному кваліфікованому імені класу є помилка друку або неправильний синтаксис або він не існує на передбаченому шляху .

Не вдалося завантажити основний клас, коли клас неможливо ініціювати основний клас, , як правило, основний клас поширює інший клас, і цей клас не існує на передбаченому шляху.

Наприклад:

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

Якщо пружина верблюда не включена, про цю помилку буде повідомлено.


"В основному" є також багато інших категорій. І відсутня проблема суперкласу - це дуже незвичайний підзаголовок. (Настільки незвично, що я його ніколи не бачив ... у запитаннях, розміщених на цьому веб-сайті.)
Stephen C

Є ДВА, тому що помилка говорить "Не вдалося ЗНАЙТИ або ЗАМОВИТИ основний клас". Якщо є інші категорії, будь ласка, порадьте мене. Я бачив це, тому просто хочу поділитися цим тут, можливо, комусь це знадобиться.
Сяо Пен - ZenUML.com

1
Я б переглянув це на кшталт "Вам потрібно включити всі класи, необхідні для ініціації основного класу, щоб уникнути цієї конкретної помилки". Я не намагаюся тебе переконати. Я хотів би бачити це просто спосіб. Тут я залишив відповідь лише для людей, яким може подобатися читати речі таким чином. Давайте не продовжувати цю дискусію далі :) Я змінив свою заяву на "не повністю обговорюваний у прийнятій відповіді" і сподіваюся, що ви почуваєте себе краще.
Сяо Пен - ZenUML.com

5
Ця інформація є вирішальною і заслуговує на чітку згадку (це єдина відповідь, яку згадує extends). Я тільки що навчився важко, що коли основний клас не завантажується, тому що він розширює інший, який неможливо було знайти , java не повідомляє, який фактичний клас не знайдено (на відміну від NoClassDefFoundError). Так так, це трапляється, і це ситуація з підтягуванням волосся, коли ти цього не знаєш.
Hugues M.

1
У цій ситуації чи є спосіб точно сказати, який клас залежності не завантажується?
Карлос А. Ібарра

16

У мене була така помилка в цьому випадку:

java -cp lib.jar com.mypackage.Main

Він працює ;для Windows та :Unix:

java -cp lib.jar; com.mypackage.Main

Так. Це, швидше за все, тому, що ваш Mainфайл не знаходиться у файлі JAR. -cp lib.jar;означає те саме, що -cp lib.jar;. тобто поточний каталог включений на classpath.
Стівен С

Нарешті виправили проблему для unix .. дякую (працює з :)
Вікі

16

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

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

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


16

Використовуйте цю команду:

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.


Це працює лише у простих випадках. Складніші випадки вимагають більш складного класу.
Стівен C

А для >> насправді << простих випадків -cp .непотрібно, тому що якщо $CLASSPATHце не встановлено, то .це класний шлях за замовчуванням.
Stephen C

Ні, Стівен, багато разів у Windows за замовчуванням classpath не працює. Я спробував це на трьох різних машинах, ви можете спробувати і це.
shaILU

Це, мабуть, тому, що ви фактично десь встановили змінну середовища% CLASSPATH. Якщо ви це зробите, то ви не використовуєте клас за замовчуванням. (Що робить echo %CLASSPATH%вихід?) І ні, я не можу перевірити, оскільки у мене немає ПК з Windows.
Стівен C

2
Це спрацювало для мене, коли я спробував запустити просту програму з командного рядка
SnuKies

15

Іноді те, що може спричинити проблему, не має нічого спільного з основним класом, і мені довелося це знайти важко. Я переїхав до бібліотеки, на яку я посилався, і вона мені:

Не вдалося знайти або завантажити основний xxx Linux

Я просто видалив цю посилання, додав її знову, і вона спрацювала нормально.


1
Здається, що проблема полягала в тому, що у вас був неправильний класний шлях через зламану "посилання" у вашому проекті у вашому IDE. Я оновлю свою відповідь, щоб висвітлити цю справу.
Стівен С

@StephenC та EduardoDennis, Було, що і тут не вистачало баночки, в цьому банці містився інтерфейс, від якого основний клас залежав від того, щоб його було створено. Отже, повідомлення про помилку занадто широке. Я повинен сказати "не вдалося знайти", якщо файл класу не знайдено і "не вдалося завантажити (відсутні залежності)", якщо щось інше відсутнє, але не сам файл, тому повідомлення про помилку, яке є занадто широким, є оманливим, якщо зосередити увагу лише про "знайти" його частину :(
Водолій Сила

@AquariusPower - Мав би бути додатковий "викликаний" стектрейс для виключення "причина", що вказаний клас wht відсутній. Якщо ви хочете запропонувати розробникам Java змінити повідомлення про помилку, яке говорить про те, що протягом 20 років більше ... не соромтеся. (Я думаю, що повідомлення про помилку є правильним. Проблема полягала в тому, що >> ви << звузилися на неправильному пункті.)
Stephen C

@StephenC, що я мав на увазі, це вони, безумовно, мають доступ до інформації, якщо файл основного класу доступний чи ні, то чому б не показати нам краще повідомлення про помилку, вказуючи, що такий файл відсутній. З іншого боку, вони також могли сказати: "Файл знайдено, але його не вдалося завантажити" в цей момент, ми негайно зосередимось на залежностях, замість того, щоб втратити півдня на дослідження та тестування речей для розуміння. Тільки що я мав на увазі :). Вони можуть робити це обмеженим способом протягом 20 років, але вони можуть вдосконалити це, і ми тут готові, що це станеться через нашу критику та скарги! : D
Сила Водолія

Будь ласка, зрозумійте, що означав я >> Поскаржившись на це у деяких незрозумілих коментарях до трирічних запитань і запитань, нічого не вдасться досягти. Люди, які могли б сумлінно діяти за вашими скаргами, цього не помітять. Якщо ви хочете зробити щось конструктивне, подайте виправлення. (Я не оцінюю ваші шанси, але вони будуть більшими, ніж якщо ви просто обдуєте це.)
Стівен C

10

У цьому випадку у вас є:

Не вдалося знайти або завантажити основний клас ? Classpath

Це тому, що ви використовуєте "-classpath", але тире не є тим самим тире, яке використовується javaв командному рядку. У мене виникла проблема копіювання та вставлення з Блокнота до cmd.


2
Оце Так! Це абсолютно дивна причина! (Але він служить вам правильним для використання Блокнота замість реального редактора тексту :-))
Stephen C

10

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

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

У моєму випадку помилка з’явилася через те, що я поставив ім'я вихідного файлу замість імені класу.

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


Так. Дивіться мій приклад №2 неправильних способів вказати назву класу !!
Стівен С

7

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

Я склав це так:

javac HelloWorld.java

І я спробував запустити також з тим же розширенням:

java Helloworld.java

Коли я видалив .javaта переписав команду на кшталт java HelloWorld, програма працювала ідеально. :)


2
Це тому, що ви виконуєте скомпільовану версію свого .java. Фактично виконується файл .class
Jason V

Для запису це те саме, що Причина №1, Приклад №5 у моїй відповіді ...
Стівен C

6

Усі відповіді тут спрямовані на користувачів Windows, здається. Для Mac роздільник класового шляху є :, ні ;. Оскільки помилка при встановленні classpath за допомогою ;не викидається, це може виявити важко, якщо ви переходите з Windows на Mac.

Ось відповідна команда Mac:

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

Там, де в цьому прикладі є пакет com.testі libпапка, яка також повинна бути включена на classpath.


2
На Linux так само, як і на Mac.
Alex78191

Навіщо /*це потрібно?
Alex78191

Це синтаксис підстановки. (Це не є обов'язковим. Ви можете чітко перелічити JAR, якщо хочете.)
Стівен C

6

введіть тут опис зображення

Розташування файлу класу: C: \ test \ com \ company

Назва файлу: Main.class

Повністю кваліфікована назва класу: com.company.Main

Команда командного рядка:

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

Зауважте тут, що шлях до класу НЕ включає \ com \ company


6

Я витратив гідну кількість часу, намагаючись вирішити цю проблему. Я думав, що я якось неправильно встановлював свій класний шлях, але проблема полягала в тому, що я набрав:

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

замість:

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

Я подумав, що значення цілком кваліфікованого означає включати повну назву шляху замість повної назви пакета.


Я оновив свою відповідь, щоб спробувати усунути цю плутанину.
Стівен C

2
Жодне з них не є правильним. Клас повинен бути вказаний як utilities.myapp.Coolабо як його назва пакету, якщо він є.
користувач207421

5

Спочатку встановіть шлях за допомогою цієї команди;

set path="paste the set path address"

Потім потрібно завантажити програму. Наберіть "cd (ім'я папки)" на збереженому диску і компілюйте його. Наприклад, якщо моя програма зберігається на дисководі D, введіть "D:", натисніть клавішу enter і введіть "cd (назва папки)".


4
Це не допомагає. Це питання стосується програм Java, а не звичайних виконуваних файлів. Java не використовує PATH, щоб знайти що-небудь, і якщо "cd" допомагає, то це скоріше, ніж удача, а не судження.
Стівен С

if "cd" helps then it by luck rather than by judgement. Це неправильно (я вважаю), оскільки java використовує поточний каталог .як частину classpath за замовчуванням.
GKFX

2
@GKFX - Це я маю на увазі. Якщо ви не знаєте, що ви використовуєте classpath за замовчуванням (або classpath з "." На ньому), "cd" не матиме ефекту. Це рішення працює більше, ніж удача (тобто вгадування / сподівання, що "." Стоїть на класі), ніж через судження (тобто перевірка того, що "." Стоїть на класі). Крім того, ви неправильно ставитеся до замовчування. Java використовує "." як classpath за замовчуванням, а не як частина classpath за замовчуванням.
Стівен C

5

Що вирішило проблему в моєму випадку:

Клацніть правою кнопкою миші проект / клас, який потрібно запустити, а потім Run As-> Run Configurations. Тоді вам слід виправити наявну конфігурацію або додати нову наступним чином:

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


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>

4

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

Windows (тестовано з 7) не приймає спеціальних символів (наприклад á) у назвах класів та пакетів. Linux, однак, робить.

Я це з'ясував, коли створив .jarNetBeans і спробував запустити його в командному рядку. Він працював у NetBeans, але не в командному рядку.


4

У Windows .;на початку поставте значення CLASSPATH.

The. (крапка) означає "шукати в поточному каталозі". Це постійне рішення.

Також ви можете встановити його "один раз" за допомогою набору CLASSPATH=%CLASSPATH%;.. Це триватиме до тих пір, поки ваше вікно cmd буде відкрито.


1
Ця порада може допомогти чи не допомогти. Це допоможе, якщо дерево класів, що містить класи у поточному каталозі. Не буде, якщо їх немає. Я насправді цього не робив би. Натомість я створив би одношаровий скрипт для обгортки, який працював над тим, чи є користувач у "правильному" каталозі.
Стівен C

4

Вам справді потрібно зробити це з 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

2
Клас не можна назвати "CommandLine.class". Це була б помилка синтаксису Java. (Що ви маєте на увазі, що файл, що містить скомпільований клас, називається "CommandLine.class" ...). Інша проблема полягає в тому, що ваша інструкція "cd до вихідного каталогу" працює лише в тому випадку, якщо ви склали код >> у << дерево вихідного каталогу. Нарешті, якщо ваша компіляція використовувала аргумент "-cp", тоді вам потрібен еквівалент при запуску.
Стівен C

У моєму проекті є папка src та папка bin у корені. Я повинен був cdувійти, srcа потім запустити команду, java ../bin com.blah.blah.MyClassяка працювала на мене. Тож дякую за пораду!
tamj0rd2

3

У Java, коли ви іноді запускаєте JVM з командного рядка за допомогою виконуваного файлу java і намагаєтеся запустити програму з класового файлу з загальнодоступним статичним void main (PSVM), ви можете зіткнутися з помилкою нижче, хоча параметр classpath до JVM точний, і файл класу присутній на classpath:

Error: main class not found or loaded

Це відбувається, якщо файл класу з PSVM не вдалося завантажити. Однією з можливих причин цього є те, що клас може реалізовувати інтерфейс або розширювати інший клас, який відсутній на шляху. Як правило, якщо клас не знаходиться на шляху до класу, викинута помилка вказується як така. Але, якщо клас, що використовується, розширений або впроваджений, java не може завантажити сам клас.

Довідка: https://www.computingnotes.net/java/error-main-class-not-found-or-loaded/


1
Ви читали прийняту відповідь? Чи додає ваша відповідь щось нове?
Stephen C

1
@StephenC Я намагався знайти причину у вашому списку, переглядаючи категорії "Розум" та їх точки. Я не зміг знайти точку відповідності у заголовку "Причина №1" та "Причина №2", що не відповідає моєму випадку (тому що я був впевнений, що немає проблеми із самим classpath). Я знайшов причину, виконуючи експерименти, і мене здивувало, що в моєму випадку було показано помилку "основний клас не знайдено", оскільки інтерфейс реалізації не був на шляху до класу. Звичайно, ви можете сказати, що "ви повинні прочитати все, що описано в публікації", але мені здається, ваш список причин може бути покращений.
гумки

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

Я також зіткнувся з подібними помилками під час тестування з'єднання 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)

Все це передбачає, що 1) JavaMongoDBConnectionне має пакета, і 2) ви не змінюєте каталог. Воно, найменше, крихке. І не пояснюючи проблеми, це призведе до того, щоб новачки спробували цей підхід у ситуаціях, коли це не спрацює . Коротше кажучи, це заохочує "методики програмування вуду": en.wikipedia.org/wiki/Voodoo_programming
Stephen C

3

Гаразд, відповідей уже багато, але ніхто не згадав про випадок, коли винуватці дозволу на файли можуть бути винуватими.

Під час запуску користувач може не мати доступу до файлу JAR або до одного з каталогів шляху. Наприклад, врахуйте:

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

User1, якому належить файл 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. Це може призвести до того, що User1 перетворить гайки, коли User1 може бачити файли та отримувати доступ до них, але помилка все ж трапляється для User2.


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" />

2

Я не зміг вирішити цю проблему за допомогою наведених тут рішень (хоча зазначена відповідь, без сумніву, очистила мої концепції). Я стикався з цією проблемою два рази, і кожен раз, коли я пробував різні рішення (в Eclipse IDE).

  • По-перше, я зіткнувся з кількома mainметодами в різних класах свого проекту. Отже, я видалив mainметод з наступних класів.
  • По-друге, я спробував таке рішення:
    1. Клацніть правою кнопкою миші на моєму головному каталозі проекту
    2. Перейдіть до джерела, після чого очистіть і дотримуйтесь налаштувань за замовчуванням та натисніть кнопку Готово. Після деяких фонових завдань вас буде спрямовано до вашого основного каталогу проекту.
    3. Після цього я закриваю свій проект, знову відкриваю його і бум, я нарешті вирішив свою проблему.

1
Видалення mainметодів не усуне проблему. З додатком, який має кілька точок входу, технічно немає нічого поганого.
Стівен С
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.