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

1370

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

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

Стивен С
источник
37
Обратите внимание, что это вопрос с «самостоятельным ответом», предназначенный для общих справочных вопросов для новых пользователей Java. Я не смог найти существующие вопросы и ответы, которые бы адекватно освещали это (ИМО).
Стивен С

Ответы:

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") как a 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команда не может найти класс. Чтобы понять это, вам необходимо понять понятие «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 символов с веб-сайтов, документов и так далее. И рассмотрим «гомоглифы», если две буквы или символы выглядят одинаково ... но это не так.

Наконец, вы, очевидно, можете столкнуться с этой проблемой, если попытаетесь запустить файл 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, перестройка проекта и так далее.


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

Стивен С
источник
43
У меня была эта проблема, когда я пытался запустить класс со сторонней библиотекой. Я вызвал Java, как это java -cp ../third-party-library.jar com.my.package.MyClass:; это не работает, вместо этого необходимо также добавить локальную папку в путь к классу (разделенный :, как это:, java -cp ../third-party-library.jar:. com.my.package.MyClassтогда это должно работать
lanoxx
23
После многих лет программирования на Java мне все же удалось оказаться на этой странице. Для меня проблема была в том, что синтаксис classpath зависит от ОС . Я новичок в программировании на Windows и понятия не имел.
кейсер
5
Дополнительные замечания, пункт 2, спаси меня! Грустно видеть, что javaэто не говорит о том, что он не находит импортированный класс, но вместо этого основной класс, который вы пытаетесь запустить. Это вводит в заблуждение, хотя я уверен, что есть причина для этого. У меня был случай, когда я javaточно знал, где находится мой класс, однако он не смог найти один из импортированных классов. Вместо этого он пожаловался на то, что не нашел своего основного класса. Действительно, раздражает.
MSX
У меня была эта проблема дважды в Eclipse. Первый раз подпись main () была неправильной. Во второй раз я переименовал .jar, и хотя я добавил новый в путь сборки, Eclipse не нашел старый, поэтому проект не компилировался с этой ошибкой. Мне пришлось удалить файл .jar из проекта> Свойства> Путь сборки Java> Библиотеки.
GregT
Я столкнулся с этим в третий раз. Я запустил программу из пакетного файла Windows 10 и поместил имя .jar в переменную (называемую «-cp% jarname%; lib *»). Я по ошибке поставил лишний пробел в конце имени, и это вызвало ошибку. Хет-трик :)
GregT
239

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

Вы получите эту ошибку, если позвоните с помощью:

java HelloWorld.class

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

java HelloWorld
panoet
источник
3
Проблема состоит в том, что это решение работает только для классов Java, объявленных в пакете по умолчанию без зависимостей файла JAR. (И даже тогда, не всегда.) Большинство программ на Java не так просты.
Стивен С
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.

tharinduwijewardane
источник
2
Этот ответ делает целый груз предположений. И есть другие способы добиться этого. Вместо того, чтобы слепо следовать вышеприведенному совету, я бы порекомендовал людям потратить время на чтение ссылок в моем Ответе, объясняющих, как работает путь к классам Java. Лучше ПОНИМАТЬ, что вы делаете ...
Стивен С.
2
Этот ответ делает точные предположения, которые мне нужны :) Я был расположен в каталоге файла .class и java.exe не работал. Как только я cd-ed выше и бежал с именем пакета, включенным в командную строку, это работало.
Ник Константин
61

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

M-Разави
источник
1
Смотрите «Дополнительные примечания № 1» моего ответа. Для лучшего объяснения этой проблемы.
Стивен C
14
@StephenC Да, ваш ответ более полный (и, конечно, +1), но в этом конкретном ответе было слово «пакет», что позволило мне быстро найти то, что мне нужно. И это сработало. Итак +1 Разави. StephenC, у вас нет простого примера пакета, который мне нужен, так как я новичок в Java.
kmort
5
Это была именно моя проблема. Я изучал тонны документации на Java, и этот конкретный пример - то, что мне было нужно
Джон
1
Да, конкретный пример хорош, это сработало отлично. Я уверен, что основной ответ очень тщательный, но было трудно увидеть дерево для леса. Хороший @Razavi
Пиксель
1
Мне нравится этот короткий и полезный ответ вместо принятого!
Спара
46

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

javac HelloWorld.java
java -cp . HelloWorld
Энамул Хасан
источник
2
Это не очень хорошая рекомендация. Вы зависите от того, что переменная среды CLASSPATH не установлена ​​или имеет значение, соответствующее значению «.». Да, это работает во многих случаях, но не будет в других.
Стивен С.
Ну конечно javac -classpath . HelloWorld.javaбы сработало! И это лучшее решение в вашем случае.
Стивен С.
2
Если в качестве первой строки у вас указан «package com.some.address» - это не сработает. Вам нужно будет закомментировать «адрес пакета» ..
Джо
1
@Joe - этот хак (комментируя пакет) будет работать (в некоторых случаях), но это плохая идея. Лучшая идея - узнать / понять причину проблемы и найти правильное решение.
Стивен С.
36

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

  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!
Celebes
источник
3
В Ubuntu мне также пришлось указать путь. Не понимаю, почему он не может использовать Текущий рабочий каталог по умолчанию. Я убежден, что Java спонсируется производителями клавиатур!
прошло
1
@ ушел - причина, по которой "." по умолчанию не входит в $ PATH, потому что это ловушка безопасности. seas.upenn.edu/cets/answers/dot-path.html
Стивен С.
Большое спасибо за это ...... хотя и не уверен, почему 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

Если верблюжья пружина не включена, об этой ошибке будет сообщено.

Сяо Пэн - ZenUML.com
источник
«В основном» есть и много других категорий. И проблема с отсутствующим суперклассом - очень необычный случай. (Настолько необычно, что я никогда не видел это ... в вопросах, задаваемых на этом сайте.)
Стивен С.
Есть два, потому что ошибка говорит: «Не удалось найти или загрузить основной класс». Если есть другие категории, пожалуйста, сообщите мне. Я видел это, так что просто хочу поделиться этим здесь, может быть, кому-то еще это понадобится.
Сяо Пэн - 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
Yamahar1sp
источник
Да. Это, скорее всего, потому что вы Mainне в файле JAR. -cp lib.jar;означает то же самое, что -cp lib.jar;. и текущий каталог включен в путь к классам.
Стивен С
Наконец исправлена ​​проблема с Unix .. спасибо (работает с :)
Vicky
16

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

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

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

jan.supol
источник
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.

shaILU
источник
Это работает только в простых случаях. Более сложные случаи требуют более сложного пути к классам.
Стивен С.
И для >> действительно << простых случаев -cp .это не нужно, потому что если $CLASSPATHне установлено, то .это путь к классу по умолчанию.
Стивен С.
Нет, Стивен, много раз в Windows по умолчанию classpath не работает. Я попробовал это на трех разных машинах, вы можете попробовать это также.
shaILU
Вероятно, это связано с тем, что вы где-то установили переменную среды% CLASSPATH%. Если вы это сделаете, то вы не используете путь к классу по умолчанию. (Что echo %CLASSPATH%выводит?) И нет, я не могу проверить, потому что у меня нет ПК с Windows.
Стивен С.
2
Это сработало для меня, когда я попытался запустить простую программу из командной строки
SnuKies
15

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

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

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

Эдуардо Деннис
источник
1
Похоже, проблема заключалась в том, что у вас был неправильный путь к классу из-за неправильной «ссылки» в вашем проекте в вашей IDE. Я обновлю свой ответ, чтобы покрыть этот случай.
Стивен С
@StephenC и EduardoDennis, это было то, что здесь также отсутствовал jar, что jar содержал интерфейс, от которого зависел основной класс для создания экземпляра. Итак, сообщение об ошибке слишком широкое. Я должен сказать «не удалось найти», если файл класса не найден, и «не удалось загрузить (отсутствуют зависимости)», если отсутствует что-то еще, кроме самого файла, поэтому слишком широкое сообщение об ошибке приводит к ошибкам, если вы фокусируете только на «найти» его часть :(
Водолей Power
@AquariusPower - Должна быть дополнительная трассировка стека, вызванная «причиной», для исключения «причина», в котором указано, что класс отсутствует. Если вы хотите предложить разработчикам Java изменить сообщение об ошибке, в котором говорилось, что на протяжении более 20 лет ... не стесняйтесь. (Я думаю, что сообщение об ошибке правильное. Проблема заключалась в том, что >> вы << сузились в неправильном предложении.)
Стивен C
@StephenC, что я имел в виду, они, безусловно, имеют доступ к информации, если файл основного класса доступен или нет, так почему бы не показать нам лучшее сообщение об ошибке, говорящее, что такой файл отсутствует. С другой стороны, они могли бы также сказать «Файл был найден, но не может быть загружен» в этот момент, мы бы быстро сосредоточились на зависимостях, вместо того, чтобы тратить полдня на изучение и тестирование для понимания. Именно это я и имел ввиду :). Они могут делать это ограниченным образом в течение 20 с лишним лет, но они могут улучшить его, и мы здесь для того, чтобы это произошло благодаря нашей критике и жалобам! : D
Водолей Power
Пожалуйста, поймите, что я имел в виду. Жаловаться на это в каком-то неясном комментарии к 3-летнему Q & A ничего не добьется. Люди, которые могут обоснованно реагировать на ваши жалобы, не заметят этого. Если вы хотите сделать что-то конструктивное, отправьте патч. (Я не оцениваю ваши шансы, но они будут больше, чем если бы вы просто об этом поругались.)
Стивен С.
10

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

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

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

Натан Уильямс
источник
2
Вот Это Да! Это совершенно странная причина! (Но он подходит вам для использования Блокнота вместо реального текстового редактора :-))
Стивен С.
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

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

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

KawaiKx
источник
Да. Смотрите мой пример № 2 неправильных способов указать имя класса!
Стивен С.
7

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

Я скомпилировал это так:

javac HelloWorld.java

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

java Helloworld.java

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

Рамеш Парик
источник
2
Это потому, что вы выполняете скомпилированную версию вашего .java. Это на самом деле исполняется файл .class
Jason V
Для записи, это то же самое, что и причина № 1, пример № 5 в моем ответе ...
Стивен С.
6

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

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

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

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

голубое небо
источник
2
На Linux так же, как на Mac.
Alex78191
Зачем /*это нужно?
Alex78191
Это подстановочный синтаксис. (Это не обязательно. Вы можете явно указать JAR-файлы, если хотите.)
Стивен С.
6

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

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

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

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

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

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

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

developer747
источник
6

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

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

вместо:

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

Я думал, что значение «полный» означает включение полного пути вместо полного имени пакета.

mathewbruens
источник
Я обновил свой ответ, чтобы попытаться устранить эту путаницу.
Стивен С
2
Ни один из них не является правильным. Класс должен быть задан как utilities.myapp.Coolили как его имя пакета, если таковое имеется.
Маркиз Лорн
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 использует текущий каталог .как часть пути к классам по умолчанию.
GKFX
2
@GKFX - Это то, что я имею в виду. Если вы не знаете, что используете стандартный путь к классам (или путь к классам с «.», «Cd» не будет иметь никакого эффекта. Это решение работает больше благодаря удаче (т.е. угадывание / надежда, что «.» Находится на пути к классам), чем по суждению (то есть проверка того, что «.» Находится на пути к классам). Кроме того, вы ошибаетесь по умолчанию. Java использует "." как путь к классам по умолчанию, а не как часть пути к классам по умолчанию.
Стивен С
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 делает, хотя.

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

GuiRitter
источник
4

В Windows .;укажите значение CLASSPATH в начале.

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

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

Ненад Булатович
источник
1
Этот совет может или не может помочь. Это поможет, если дерево классов содержит классы в текущем каталоге. Это не будет, если они не. Я бы на самом деле не делал этого. Вместо этого я бы создал однострочный скрипт-обертку, который работал бы независимо от того, находится ли пользователь в «правильном» каталоге.
Стивен С
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
Майк. D
источник
2
Класс не может называться «CommandLine.class». Это было бы синтаксической ошибкой Java. (Вы имеете в виду, что файл, содержащий скомпилированный класс, называется «CommandLine.class» ...). Другая проблема заключается в том, что ваша инструкция «cd to source directory» работает только в том случае, если вы скомпилировали код >> в << дерево каталогов исходного кода. Наконец, если ваша компиляция использовала аргумент "-cp", вам нужен эквивалент при запуске.
Стивен С.
В моем проекте у меня есть папка src и папка bin в корне. Я должен был cdв srcи затем запустить команду, java ../bin com.blah.blah.MyClassкоторая работала для меня. Так что спасибо за совет!
tamj0rd2
3

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

Анандараджа Рави
источник
1
Вы прочитали принятый ответ? Ваш ответ добавляет что-нибудь новое?
Стивен С
1
@StephenC Я пытался найти причину в вашем списке, просматривая категории «Причина» и их пункты. Я не смог найти точки совпадения в заголовке «Причина № 1» и «Причина № 2», который не выглядел близко к моему случаю (потому что я был уверен, что с самим classpath проблем нет). Я нашел причину, выполняя эксперименты, и был удивлен, что в моем случае была показана ошибка «main class not found», потому что интерфейс реализации не был на пути к классам. Конечно, вы можете сказать: «Вы должны прочитать все, что описано в посте», но мне кажется, ваш список причин может быть улучшен.
Gumkins
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.

Chezzwizz
источник
3

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

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

Обобщение:

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

Запустить:

java -cp mongo-java-driver-3.4.1.jar: JavaMongoDBConnection
  • Пожалуйста, соблюдайте двоеточие (Unix) / запятую (Windows) после завершения всех файлов JAR зависимости
  • В конце обратите внимание на имя основного класса без каких-либо расширений (без .class или .java)
khichar.anil
источник
Все это предполагает, что 1) JavaMongoDBConnectionне имеет пакета и 2) вы не меняете каталог. Это, по меньшей мере, хрупко. И не объясняя проблемы, это заставит новичков попробовать этот подход в ситуациях, когда он не будет работать . Короче говоря, он поощряет «методы программирования вуду»: en.wikipedia.org/wiki/Voodoo_programming
Стивен С.
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.

biocyberman
источник
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. Идите к источнику, затем очистите и придерживайтесь настроек по умолчанию и на Finish. После некоторых фоновых заданий вы будете перенаправлены в основной каталог проекта.
    3. После этого я закрываю свой проект, снова открываю его, и бум, я наконец-то решил свою проблему.
Анус Калим
источник
1
Удаление mainметодов не решит проблему. Технически нет ничего плохого в приложении с несколькими точками входа.
Стивен С