"Could not find or load main class"是什么意思?
新 Java 开发人员遇到的一个常见问题是他们的程序无法运行并显示错误消息:Could not find or load main class ...
这是什么意思,是什么原因造成的,以及应该如何解决?
java <class-name>
命令语法
首先,您需要了解使用java
(或javaw
)命令启动程序的正确方法。
正常语法1是这样的:
java [ <options> ] <class-name> [<arg> ...]
其中 <option>
是命令行选项(以“-”字符开头),<class-name>
是完全限定的 Java 类名,<arg>
是传递到应用程序的任意命令行参数。
1 - 在本答案末尾附近描述了一些其他语法。
类的完全限定名 (FQN) 按照惯例按照 Java 源代码中的方式编写;例如
packagename.packagename2.packagename3.ClassName
然而,java
命令的某些版本允许您使用斜杠而不是句点;例如
packagename/packagename2/packagename3/ClassName
它(令人困惑地)看起来像一个文件路径名,但实际上不是。请注意,术语完全限定名称是标准Java术语......不是我为了让您感到困惑而编造的东西:-)
以下是 java
命令的示例:
java -Xmx100m com.acme.example.ListUsers fred joe bert
上述内容将导致java
命令执行以下操作:
- 搜索
com.acme.example.ListUsers
类的编译版本。 - 加载类。
- 检查该类是否有一个
main
方法,其签名、返回类型和修饰符 如public static void main(String[])
所示。 (请注意,方法参数的名称不是签名的一部分。) - 调用该方法,将命令行参数(“fred”、“joe”、“bert”)作为
String[]
传递给它。
Java找不到类的原因
当您收到消息"Could not find or load main class ..."时,这意味着第一步失败了。 java
命令无法找到该类。事实上,消息中的“...”将是java
正在寻找的完全限定类名。
那么为什么会找不到班级呢?
原因#1 - 你在类名参数上犯了一个错误
第一个可能的原因是您可能提供了错误的类名。 (或者......正确的类名,但形式错误。)考虑上面的示例,这里有各种指定类名的错误方法:
示例#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 - 应用程序的classpath指定不正确
第二个可能的原因是类名是正确的,但java
命令找不到该类。要理解这一点,您需要理解“classpath”的概念。 Oracle 文档对此进行了很好的解释:
java
命令文档- 设置classpath。
- Java 教程 - PATH 和 CLASSPATH
所以...如果您正确指定了类名,接下来要检查的是您是否正确指定了classpath:
- 阅读上面链接的三个文档。 (是的......阅读它们!Java 程序员至少要理解 Java 类路径机制如何工作的基础知识,这一点很重要。)
- 查看运行
java
命令时有效的命令行和/或 CLASSPATH 环境变量。检查目录名和 JAR 文件名是否正确。 - 如果classpath中有相对路径名,请检查它们是否从运行
java
命令时有效的当前目录正确解析。 - 检查该类(错误消息中提到的)是否可以位于有效classpath上。
- 请注意,Windows 与 Linux 和 Mac OS 的classpath语法不同。 (classpath分隔符在 Windows 上为
;
,在其他平台上为:
。如果您在您的平台上使用了错误的分隔符,您将不会收到明确的错误消息。相反,路径上会出现一个不存在的文件或目录,并被默默忽略。)
原因 #2a - classpath上的目录错误
当您将目录放在classpath上时,它理论上对应于限定名称空间的根。类位于根目录下的目录结构中,通过将完全限定名称映射到路径名。例如,如果“/usr/local/acme/classes”位于classpath上,那么当 JVM 查找名为 com.acme.example.Foon
的类时,它将查找具有以下路径名的“.class”文件:
/usr/local/acme/classes/com/acme/example/Foon.class
如果您将“/usr/local/acme/classes/com/acme/example”放在classpath中,那么 JVM 将无法找到该类。
原因 #2b - 子目录路径与 FQN 不匹配
如果您的类 FQN 是 com.acme.example.Foon
,那么 JVM 将在目录“com/acme/example”中查找“Foon.class”:
如果您的目录结构与上述模式中的包命名不匹配,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
笔记:
- 在大多数 Java 版本中,
-classpath
选项可以缩写为-cp
。检查java
、javac
等相应的手册条目。 - 在classpath中的绝对路径名和相对路径名之间进行选择时请仔细考虑。请记住,如果当前目录发生更改,相对路径名可能会“中断”。
原因 #2c - classpath中缺少依赖项
classpath需要包含应用程序依赖的所有其他(非系统)类。 (系统类是自动定位的,您很少需要关心这一点。)为了正确加载主类,JVM 需要找到:
- class本身。
- 超类层次结构中的所有类和接口(例如,请参阅classpath中存在 Java class is present in classpath but startup fails with Error: Could not find or load main class)
- 通过变量或变量声明、方法调用或字段访问表达式引用的所有类和接口。
(注意:JLS 和 JVM 规范允许 JVM 在一定范围内“延迟”加载类,这可能会影响抛出类加载器异常的时间。)
原因 #3 - 该类已在错误的包中声明
偶尔会发生这样的情况:有人将源代码文件放错了源代码树中的文件夹,或者漏掉了 package
声明。如果您在 IDE 中执行此操作,IDE 的编译器会立即告诉您这一点。同样,如果您使用合适的 Java 构建工具,该工具将以检测问题的方式运行 javac
。但是,如果您手动构建 Java 代码,则可以采用编译器不会注意到问题的方式,并且生成的“.class”文件不会位于您期望的位置。
还是找不到问题?
需要检查的东西很多,而且很容易漏掉一些东西。尝试将-Xdiag
选项添加到java
命令行(作为java
之后的第一件事)。它会输出有关类加载的各种信息,这可能会为您提供有关真正问题是什么的线索。
另外,请考虑从网站、文档等复制和粘贴不可见或非 ASCII 字符可能导致的问题。并考虑“同形文字”,其中两个字母或符号看起来相同......但事实并非如此。
如果META-INF/*.SF
中的签名无效或不正确,您可能会遇到此问题。您可以尝试在您最喜欢的 ZIP 编辑器中打开 .jar,然后从 META-INF
中删除文件,直到只剩下 MANIFEST.MF
。然而,一般情况下不建议这样做。 (无效签名可能是由于有人将恶意软件注入到原始签名的 JAR 文件中而导致的。如果删除无效签名,您的应用程序就会被恶意软件感染!)建议的方法是获取具有有效签名的 JAR 文件。签名,或从(真实的)原始源代码重建它们。
最后,如果 MANIFEST.MF
文件中存在语法错误,您显然会遇到此问题(请参阅 https://stackoverflow.com /a/67145190/139985)。
java
的替代语法
使用java command
启动Java程序有三种替代语法。
用于启动“可执行”JAR 文件的语法如下:
java [ <options> ] -jar <jar-file-name> [<arg> ...]
例如
java -Xmx100m -jar /usr/local/acme-example/listuser.jar fred
入口点类的名称(即
com.acme.example.ListUser
)和classpath在 JAR 文件的 MANIFEST 中指定。使用以下语法,您在命令行上指定为classpath的任何内容都将被忽略:仅使用清单中的Class-Path
条目(以及该条目引用的任何 JAR 文件中的条目)。另请注意,此Class-Path
中的 URL相对于它所包含的 JAR 的位置。从模块(Java 9 及更高版本)启动应用程序的语法如下:
java [ <options> ] --module <module>[/<mainclass>] [<arg> ...]
入口点类的名称要么由
<module>
本身定义,要么由可选的<mainclass>
给出。从 Java 11 开始,您可以使用
java
命令使用以下语法来编译和运行单个源代码文件:java [ <options> ] <sourcefile> [<arg> ...]
其中
<sourcefile>
(通常)是后缀为“.java”的文件。
有关更多详细信息,请参阅您所使用的 Java 版本的 java
命令的官方文档。
IDE
典型的 Java IDE 支持在 IDE JVM 本身或子 JVM 中运行 Java 应用程序。这些通常不受此特定异常的影响,因为 IDE 使用自己的机制来构造运行时classpath、识别主类并创建 java
命令行。
但是,如果您在 IDE 后面执行操作,则仍然有可能发生此异常。例如,如果您之前在 Eclipse 中为 Java 应用程序设置了应用程序启动器,然后将包含“主”类的 JAR 文件移动到文件系统中的其他位置,没有告诉 Eclipse ,Eclipse 会无意中使用不正确的类路径启动 JVM。
简而言之,如果您在 IDE 中遇到此问题,请检查 IDE 状态是否陈旧、项目引用损坏或启动器配置损坏等。
IDE 也可能会感到困惑。 IDE 是非常复杂的软件,由许多交互部分组成。其中许多部分采用了各种缓存策略,以使 IDE 作为一个整体具有响应能力。这些有时可能会出错,一种可能的症状是启动应用程序时出现问题。如果您怀疑可能会发生这种情况,则值得尝试其他方法,例如重新启动 IDE、重建项目等。
其他参考资料
- 来自 Oracle Java 教程 - 常见问题(及其解决方案)
java -cp ../third-party-library.jar com.my.package.MyClass
;这不起作用,而是需要将本地文件夹也添加到类路径中(用:
分隔,如下所示:java -cp ../third-party-library.jar:. com.my.package.MyClass
,然后它应该可以工作
- lanoxx 2014-02-08
java
并没有说它没有找到导入的类,而是说您正在尝试运行的主类。这是一种误导,尽管我确信这是有原因的。我遇到过这样的情况:java
确切地知道我的类在哪里,但它找不到导入的类之一。它没有这么说,而是抱怨找不到我的主类。确实,烦人。
- MSX 2016-10-03
如果您的源代码名称是HelloWorld.java,则编译后的代码将为HelloWorld.class
。
如果您使用以下方式调用它,您将收到该错误:
java HelloWorld.class
相反,使用这个:
java HelloWorld
javac TestCode.java
,然后是java TestCode
- Someone Somewhere 2016-01-03
java -classpath . HelloWorld
- Chris Prince 2017-01-31
如果您的类位于包中,那么您必须 cd
到项目的根目录并使用该类的完全限定名称 (packageName.MainClassName) 运行。
例子:
我的class在这里:
D:\project\com\cse\
我的主类的完全限定名称是:
com.cse.Main
所以我cd
回到项目根目录:
D:\project
然后发出java
命令:
java com.cse.Main
这个答案是为了让 Java 新手程序员免受常见错误带来的挫败感。我建议您阅读已接受的答案,以更深入地了解 Java 类路径。
java com.firstpackage.Test
不起作用,命令 java -classpath C:\Users\matuagkeetarp\IdeaProjects\Helloworld\src\com\firstpackage Test.java
set classpath 变量也不起作用。你能帮我吗?
- Prateek Gautam 2021-11-15
使用关键字“package”
如果源代码中有package
关键字(主类在包中定义),则应使用类的全名(packageName.MainClassName
)。
假设有一个源代码文件(Main.java):
package com.test;
public class Main {
public static void main(String[] args) {
System.out.println("salam 2nya\n");
}
}
要运行此代码,您应该将 Main.Class
放在类似包的目录中:
C:\Users\workspace\testapp\com\test\Main.Java
然后将终端的当前目录更改为项目的根目录:
cd C:\Users\workspace\testapp
最后,运行代码:
java com.test.Main
没有关键字“package”
如果您的源代码名称中没有任何包,则可能您使用了错误的命令。假设你的Java文件名为Main.java
,编译后:
javac Main.java
你编译后的代码将是Main.class
如果您使用以下方式调用它,您将收到该错误:
java Main.class
相反,使用这个:
java Main
当相同的代码在一台 PC 上运行,但在另一台 PC 上显示错误时,我发现的最佳解决方案是按如下方式进行编译:
javac HelloWorld.java
java -cp . HelloWorld
javac -classpath . HelloWorld.java
肯定会起作用!对于您的情况来说,这是一个更好的解决方案。
- Stephen C 2015-08-22
在命令行上指定类路径对我很有帮助。例如:
创建一个新文件夹
C:\temp
在
C:\temp
中创建文件Temp.java,其中包含以下类:public class Temp { public static void main(String args[]) { System.out.println(args[0]); } }
在文件夹
C:\temp
中打开命令行,并编写以下命令来编译Temp类:javac Temp.java
运行编译后的 Java 类,添加
-classpath
选项让 JRE 知道在哪里可以找到该类:java -classpath C:\temp Temp Hello!
java
没有查看 $CLASSPATH(因为您使用了 -classpath 或 -jar)或 2)未在不存在的环境中设置类路径设置在运行 java
的上下文中产生效果;例如因为您没有“获取”在正确的 shell 中添加 setenv 命令的文件。
- Stephen C 2016-03-15
根据错误消息(“Could not find or load main class”),有两类问题:
- 无法找到主类
- 主类无法加载(这种情况在接受的答案中没有充分讨论)
当完全限定的类名中存在拼写错误或语法错误或者在提供的类路径中不存在时,无法找到主类。
当类无法启动时,无法加载主类。通常,主类扩展另一个类,并且该类不存在于提供的类路径中。
例如:
public class YourMain extends org.apache.camel.spring.Main
如果不包含camel-spring,就会报这个错误。
extends
的答案)。我刚刚经历了惨痛的教训,当主类由于扩展了另一个无法找到的类而无法加载时,java 不会报告哪个实际类是未找到(与NoClassDefFoundError
不同)。所以,是的,它确实发生了,而且当你不知道这一点时,这是一个令人烦恼的情况。
- Hugues M. 2017-05-31
使用这个命令:
java -cp . [PACKAGE.]CLASSNAME
示例:如果您的类名是从 Hello.java 创建的 Hello.class,则使用以下命令:
java -cp . Hello
如果您的文件 Hello.java 位于 com.demo 包内,则使用以下命令
java -cp . com.demo.Hello
使用 JDK 8 很多时候,类文件出现在同一个文件夹中,但 java
命令需要类路径,因此我们添加 -cp .
以将当前文件夹作为参考类路径。
-cp .
,因为如果未设置 $CLASSPATH
,.
就是默认的 classpath。
- Stephen C 2017-03-07
echo %CLASSPATH%
输出什么?)不,我无法检查,因为我没有 Windows PC。
- Stephen C 2017-05-05
我在这种情况下遇到了这样的错误:
java -cp lib.jar com.mypackage.Main
它适用于 Windows 的 ;
和 Unix 的 :
:
java -cp lib.jar; com.mypackage.Main
Main
不在 JAR 文件中。 -cp lib.jar;
与 -cp lib.jar;.
含义相同,即当前目录包含在类路径中。
- Stephen C 2016-09-22
尝试-Xdiag。
Steve C 的回答 很好地涵盖了可能的情况,但有时确定类是否无法找到或加载可能并不那么容易。使用java -Xdiag
(自 JDK 7 起)。这会打印出一个很好的堆栈跟踪,它提供了消息 Could not find or load main class
消息含义的提示。
例如,它可以向您指出主类使用的其他类无法找到并阻止加载主类。
有时,导致问题的原因可能与主类无关,我就是通过这种艰难的方式发现这一点的。我移动了一个引用库,结果出现了以下问题:
Could not find or load main class xxx Linux
我刚刚删除了该引用,然后再次添加它,并且它再次正常工作。
我遇到了同样的问题,终于发现了我的错误:) 我使用这个命令进行编译并且它工作正常:
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
在这种情况下,您有:
Could not find or load main class?classpath
这是因为您使用的是“-classpath”,但破折号与命令提示符上java
使用的破折号不同。我在从 记事本 复制并粘贴到 cmd 时遇到此问题。
如果您使用 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>
就我而言,出现错误是因为我提供了源文件名而不是类名。
我们需要向解释器提供包含 main 方法的类名。
类文件位置: C:\test\com\company
文件名: Main.class
完全限定类名: com.company.Main
命令行命令:
java -classpath "C:\test" com.company.Main
请注意,类路径不包含\com\company。
这里的所有答案似乎都是针对 Windows 用户的。对于 Mac,类路径分隔符是 :
,而不是 ;
。由于不会抛出使用 ;
设置类路径的错误,因此如果从 Windows 到 Mac,这可能很难发现。
这是对应的Mac命令:
java -classpath ".:./lib/*" com.test.MyClass
在此示例中,包为 com.test
,并且 lib
文件夹也将包含在类路径中。
/*
是必要的?
- Alex78191 2017-10-04
如果您的情况与我的情况特别相似,这可能会对您有所帮助:作为初学者,当我尝试运行 Java 程序时,我也遇到了这个问题。
我是这样编译的:
javac HelloWorld.java
我也尝试使用相同的扩展名运行:
java Helloworld.java
当我删除.java
并重写命令如java HelloWorld
时,程序运行完美。 :)
我认为我以某种方式错误地设置了类路径,但问题是我输入了:
java -cp C:/java/MyClasses C:/java/MyClasses/utilities/myapp/Cool
代替:
java -cp C:/java/MyClasses utilities/myapp/Cool
我认为完全限定的含义意味着包含完整路径名而不是完整包名。
utilities.myapp.Cool
或其包名称(如果有)的形式给出。
- user207421 2018-02-07
当使用 Windows PowerShell 中的 -cp
选项运行 java
时,您可能会收到类似于以下内容的错误:
The term `ClassName` is not recognized as the name of a cmdlet, function, script ...
为了让 PowerShell 接受该命令,-cp
选项的参数必须包含在引号中,如下所示:
java -cp 'someDependency.jar;.' ClassName
以这种方式形成命令应该允许 Java 正确处理类路径参数。
在 Windows 上,将 .;
放在 CLASSPATH 值的开头。
这.
(点)表示“在当前目录中查找”。这是一个永久的解决方案。
您也可以使用 set CLASSPATH=%CLASSPATH%;.
将其设置为“一次”。只要您的 cmd 窗口打开,该状态就会持续。
这是一个具体案例:
Windows(使用 Windows 7 进行测试)不接受以下格式的特殊字符(例如 á
)类和包名称。但 Linux 确实如此。
当我在 NetBeans 中构建 .jar
并尝试在命令中运行它时,我发现了这一点。它在 NetBeans 中运行,但不在命令行上运行。
解决我的问题的方法是:
右键单击要运行的项目/类,然后选择“运行方式”→“运行配置”。然后您应该修复现有配置或通过以下方式添加新配置:
打开类路径选项卡,单击高级...按钮,然后添加项目的bin
文件夹。
首先使用此命令设置路径;
set path="paste the set path address"
然后你需要加载程序。在存储的驱动器中输入“cd(文件夹名称)”并编译。例如,如果我的程序存储在D驱动器上,则输入“D:”按回车键并输入“cd(文件夹名称)”。
if "cd" helps then it by luck rather than by judgement
。这是错误的(我相信),因为 java 默认使用当前目录 .
作为类路径的一部分。
- GKFX 2014-03-31
在 Java 中,当您有时使用 Java 解释器可执行文件从命令行运行 JVM 并尝试使用 public static void main
(PSVM) 从类文件启动程序时,您可能会遇到以下错误,即使类路径参数为JVM 是准确的,并且类文件存在于类路径中:
Error: main class not found or loaded
如果无法加载带有 PSVM 的类文件,就会发生这种情况。一个可能的原因是该类可能正在实现一个接口或扩展不在类路径上的另一个类。通常,如果类不在类路径上,则抛出的错误会指出这一点。但是,如果正在使用的类被扩展或实现,Java 就无法加载该类本身。
参考: https://www.computingnotes.net /java/error-main-class-not-found-or-loaded/
您确实需要从 src
文件夹执行此操作。您可以在其中键入以下命令行:
[name of the package].[Class Name] [arguments]
假设您的类名为CommandLine.class
,代码如下所示:
package com.tutorialspoint.java;
/**
* Created by mda21185 on 15-6-2016.
*/
public class CommandLine {
public static void main(String args[]){
for(int i=0; i<args.length; i++){
System.out.println("args[" + i + "]: " + args[i]);
}
}
}
然后你应该 cd
到 src 文件夹,你需要运行的命令如下所示:
java com.tutorialspoint.java.CommandLine this is a command line 200 -100
命令行上的输出将是:
args[0]: this
args[1]: is
args[2]: a
args[3]: command
args[4]: line
args[5]: 200
args[6]: -100
cd
进入src
,然后运行对我有用的命令java ../bin com.blah.blah.MyClass
。所以谢谢你的提示!
- tamj0rd2 2017-07-21
我在测试 Java MongoDB JDBC 连接时也遇到了类似的错误。我认为简短地总结我的最终解决方案是很好的,以便将来任何人都可以直接查看这两个命令,并有利于进一步进行。
假设您位于 Java 文件和外部依赖项(JAR 文件)所在的目录中。
编译:
javac -cp mongo-java-driver-3.4.1.jar JavaMongoDBConnection.java
- -cp - 类路径参数;将所有依赖的JAR文件一一传递
- *.java - 这是具有 main 方法的 Java 类文件。 SDSD
运行:
java -cp mongo-java-driver-3.4.1.jar: JavaMongoDBConnection
- 所有依赖 JAR 文件结束后,请务必遵守冒号 (Unix)/逗号 (Windows)
- 最后,观察没有任何扩展名的主类名称(没有 .class 或 .java)
JavaMongoDBConnection
没有软件包,2) 您不更改目录。至少可以说,它是脆弱的。如果不解释问题,就会导致新手在不起作用的情况下尝试这种方法。简而言之,它鼓励“巫毒编程技术”:en.wikipedia.org/wiki/Voodoo_programming
- Stephen C 2018-01-27
好吧,已经有很多答案了,但没有人提到文件权限可能是罪魁祸首的情况。
运行时,用户可能无权访问 JAR 文件或路径的目录之一。例如,考虑:
/dir1/dir2/dir3/myjar.jar
中的 jar 文件
拥有 JAR 文件的 User1 可以执行以下操作:
# 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 可以看到这些文件并可以访问这些文件时,可能会让人抓狂,但 User2 仍然会发生错误。
我无法用此处所述的解决方案解决这个问题(尽管所述答案无疑已经澄清了我的概念)。我遇到这个问题两次,每次我都尝试不同的解决方案(在 Eclipse IDE 中)。
- 首先,我在项目的不同类中遇到了多个
main
方法。因此,我从后续类中删除了main
方法。 - 其次,我尝试了以下解决方案:
- 右键单击我的主项目目录。
- 前往源代码,然后进行清理并坚持使用默认设置,然后单击“完成”。完成一些后台任务后,您将被引导到主项目目录。
- 之后我关闭我的项目,重新打开它,然后,我终于解决了我的问题。
main
方法不会解决问题。具有多个入口点的应用程序在技术上没有任何问题。
- Stephen C 2017-01-27
有时,在您可能尝试过的某些在线编译器中,如果您不写public class [Classname]
而只写class [Classname]
,则会收到此错误。
public
是常规/正常的做法,但 Java 规范并不要求这样做,标准 Oracle / OpenJDK java
命令也没有要求。
- Stephen C 2018-07-23
就我而言,我收到错误是因为我在 Windows 7 系统上混合了大小写包名称。将包名称更改为全部小写解决了该问题。 另请注意,在这种情况下,我将 .java 文件编译为 .class 文件时没有出现错误;它只是不会从同一个(子子子子)目录运行。
我有一个奇怪的:
Error: Could not find or load main class mypackage.App
事实证明,我在项目的 pom.xml
文件中编码了 POM (父级)的引用(我的项目的 pom.xml
指向父级 pom.xml
),而 relativePath
已关闭/错误的。
以下是我的项目的pom.xml
文件的一部分:
<parent>
<groupId>myGroupId</groupId>
<artifactId>pom-parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../badPathHere/pom.xml</relativePath>
</parent>
一旦我解析了 POMrelativePath,错误就消失了。
去搞清楚。
这是另一个花了我一些时间的问题:命令行类路径参数的行为不符合您的预期。我在 MacOS 上直接调用 CLI,并且在调用中包含两个 jar。
例如,这两个都使工具对主类的名称感到困惑:
这是因为星号导致它错误地解析参数:
java -cp path/to/jars/* com.mypackage.Main
这是因为——我不知道为什么:
java -cp "*.jar" com.mypackage.Main
这有效:
java -cp "path/to/jars/*" com.mypackage.Main
明确列出两个 jar 也有效:
java -cp path/to/jars/jar1.jar:path/to/jars/jar2.jar com.mypackage.Main
*
由 shell 扩展为 JAR 文件名列表 用空格分隔 ...除非用引号引起来。这是标准的 UNIX shell 内容。至于其余的:包括:
和通配符语法("path/to/jars/*"
)的使用,都在java
手册条目中。
- Stephen C 2019-11-27
java
命令不理解该通配符。 java
手册解释了它所理解的内容。
- Stephen C 2019-11-28
经过两天的搜索,我找到了这个解决方案并且有效。这很奇怪,但对我有用。
package javaapplication3;
public class JavaApplication3 {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
System.out.println("Hello");
}
}
这是我想要运行的程序,位于 C:\Java Projects\JavaApplication3\src\javaapplication3
现在在此位置打开 cmd 并使用此命令编译程序
javac JavaApplication3.java
编译后,向下导航一个目录,即 C:\Java Projects\JavaApplication3\src
现在运行以下命令来执行程序
java javaapplication3.JavaApplication3
package javaapplication3;
语句。
- Stephen C 2020-09-17
场景:使用命令提示符(Windows 中的CMD)来编译并运行一个简单的“java”程序,该程序具有仅具有指定“package main”的“Main.java”文件。
源文件路径:
某些项目名称文件夹\src\main\Main.java
目标文件夹:
某些项目名称文件夹\dest
目标文件路径(文件夹“\main”和文件“\Main.class”将由“javac”生成):
一些项目名称文件夹\dest\main\Main.class
Main.java如下:
package main;
public class Main {
public static void main(String[] args) {
System.out.println("Hello world");
}
}
编译:
// 'javac' compiler will produce 'Main.class' in the 'dest\main' folder.
// 'main' folder is created because in the source file(in our case: 'Main.java') is
// specified 'package main'.
javac -d ./dest ./src/main/Main.java
运行编译后的文件(在我们的例子中:“Main.class”):
// '-cp'(is the same as '-classpath')
// './dest'(means destination folder, where resides compiled 'Main.class').
// 'main.Main'(means 'package' 'main', which contains class 'Main'('Main.class'))
// WARNING: when run 'java' class, MUST NOT type extension '.class'
// after 'class name
// (in our case: 'main.Main'(<package>.<class-name>) WITHOUT extension
// '.class').
java -cp ./dest main.Main
// Hello world
我在执行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" />
我上升了一级。所以,现在 HelloWorld.class 文件位于 hello\HelloWorld.class 中,我运行了以下命令。其中cp是类路径,.
表示仅检查当前目录。
java -cp . hello.HelloWorld
输出
Hello world!
package hello;
语句的 HelloWorld
类。 (这是他所做的唯一可行的方法。)
- Stephen C 2022-07-04
到目前为止,在所有答案中,还没有人指出关于应用程序类路径的正确规范的这个严重陷阱:
如果您的应用程序和依赖项在文件系统上打包为 jar,并且您尝试使用 java [options] <mainclass>
变体运行它,那么在 CLASSPATH 中提供目录名称是不够的!您必须添加/*
通配符!
文档有点难以捉摸这:
If the class path option isn't used and [CLASSPATH] isn't set, then the user class path consists of the current directory (.).
...
这句话会让你认为默认情况下运行java com.acme.example.Gerbera
当前目录中所有需要的jar肯定会起作用。唉,事实并非如此。您需要进一步阅读文档。您需要做的是 CLASSPATH=./* java com.acme.example.Gerbera
,或者使用适当的分隔符逐字枚举所有 .jar 文件名。
在 IDE 开发(Eclipse、NetBeans 或其他)的上下文中,您必须配置项目属性以拥有主类,以便您的 IDE 知道主类位于何处,以便在您点击“Play”时执行。
- 右键单击您的项目,然后属性
- 转到 "运行 "类别,选择 "主类
- 点击Run按钮。
main
的应用程序,您将不会收到上述错误消息。 (对于某些 IDE,您不需要配置启动器来实现这一点;例如 Eclipse 的 run
将找到具有 main
方法的类你。
- Stephen C 2017-08-22
Could not find or load main class ...
。这就是我写这篇文章的方式:)
- julianm 2017-08-22
main
的类,则上下文菜单中不会提供“运行”>“Java 应用程序”选项。
- Stephen C 2017-08-22
这也发生在我身上。就我而言,只有当源代码中存在HttpServlet
类时才会发生这种情况(IntelliJ IDEA没有给出编译时错误;servlet包导入得很好,但是在运行时出现了这个main class
错误) 。
我设法解决了它。我进入菜单File → Project Structure...:
然后到Modules:
servlet 模块附近有一个Provided 范围。我将其更改为Compile:
它成功了!
[Java版本:11]
如果您使用 Java 11,则无需编译和运行 java 文件。
就这样跑
Java ClassName.java
例子:
class abc{
public static void main(String[] args){
System.out.println("hello Jarvis ");
}
}
现在运行命令
java abc.java
在Intellij IDE
中选择run/debug>>edit configuration
,然后为构建和运行菜单选择适当的JDK
。
默认情况下,Java 使用当前工作目录.
作为默认CLASSPATH
。这意味着当您在提示符下键入命令时,例如java MyClass
,该命令将被解释为好像您输入了java -cp . MyClass
。你看到-cp
和MyClass
之间的那个点了吗? (cp 是较长的 classpath 选项的缩写)
这对于大多数情况来说已经足够了,并且事情似乎工作得很好,直到有一天您尝试将目录添加到CLASSPATH
。在大多数情况下,当程序员需要这样做时,他们只需运行set CLASSPATH=path\to\some\dir
这样的命令。此命令创建一个名为CLASSPATH
的新环境变量,其值为path\to\some\dir
,或者如果之前已设置CLASSPATH
,则将其值替换为path\to\some\dir
。
完成此操作后,您现在拥有一个 CLASSPATH
环境变量,并且 Java 不再使用其默认类路径 (.
),而是使用您设置的类路径。因此,第二天您打开编辑器,编写一些 java 程序 cd
到您保存它的目录,编译它,并尝试使用命令 java MyClass
运行它,您会看到一个不错的输出: Could not find or load main class ...(如果您的命令之前运行良好并且您现在得到此输出,那么您可能就是这种情况)。
发生的情况是,当您运行命令java MyClass
时,Java会在您在CLASSPATH
中设置的一个或多个目录中搜索名为MyClass
的类文件,而不是您当前的工作目录,因此它找不到您的类文件在那里,因此抱怨。
您需要做的就是再次将.
添加到您的类路径中,这可以使用命令set CLASSPATH=%CLASSPATH%;.
来完成(注意分号后面的点)。用简单的英语来说,这个命令表示“选择CLASSPATH
(%CLASSPATH%
)的最初值,将.
添加到它(;.
)并将结果分配回CLASSPATH
”。
瞧,您可以再次像往常一样使用命令java MyClass
。
解决“Could not Load main class error”
阅读完所有答案后,我发现大多数答案都不适合我。所以我做了一些研究,这就是我得到的结果。仅当步骤 1 不起作用时才尝试此操作。
- 尝试安装JRE 32或64。如果不起作用,
打开转到 C:\Program Files (x86)\Java 或 C:\Program Files\Java
- i. 打开
jdk
文件夹,然后打开bin
文件夹。 ii.复制路径并将其添加到环境变量中。确保使用分号
;
分隔变量。例如,“C:\Yargato\bin;C:\java\bin;”。如果不这样做,将会导致更多错误。iii. 转到
jre
文件夹并打开其bin
文件夹。iv. 此处搜索rt.jar 文件。我的是:
C:\Program Files (x86)\Java\jre1.8.0_73\lib\rt.jar 复制并在环境变量下搜索类路径变量 并将其粘贴到那里。
- v. 现在重新启动 cmd 并尝试再次运行。错误将会消失。
- vi。我将发布我的 YouTube 视频教程的链接。
- i. 打开
%JAVA_HOME\bin%
确实需要位于 %PATH%
上,但这会导致不同的错误。 %JAVA_HOME\lib\rt.jar%
不需要添加到类路径中。所有需要它的 JRE 或 JDK 工具都会自动将它添加到 bootclasspath 中。
- Stephen C 2018-01-04
我在 IntelliJ 中创建的演示程序遇到了这个问题。
解决这个问题有两个关键点:
- 程序的包名
- 终端/cmd 提示符的当前工作目录
我的演示程序:
package io.rlx.tij.c2;
public class Ex10 {
public static void main(String[] args) {
// do something
}
}
源代码路径:
../projectRoot/src/main/java/io/rlx/tij/c2/Ex10.java
- 转到
java
目录:cd ../projectRoot/src/main/java
- 编译为类:
javac ./io/rlx/tij/c2/Ex10.java
- 运行程序:
java io.rlx.tij.c2.Ex10
如果我在../projectRoot/src/main/java/io/rlx/tij/c2
中运行程序或者在没有包名的情况下运行它,我将收到此错误:Error: Could not find or load main class
。
- 在 IntelliJ IDEA 中,检查您的全局库*和本地库
- 检查库版本文件pom.xml,可能是旧库
- 前面的答案中提到了很多可能性,也需要尝试
就我而言,我的类引用了一个在 Eclipse 外部打开的文件。所以它无法在重新编译时重新生成类。需要确保“问题”选项卡中的所有问题均已清除。
对于 Java 17,我必须确保模块中的类之一至少有一个 main 方法。只需添加 main 方法就可以解决问题
看来当我遇到这个问题时,它是独一无二的。
一旦我删除了文件顶部的包声明,它就完美地工作了。
除此之外,似乎没有任何方法可以在我的机器上运行简单的 HelloWorld.java,无论编译发生在哪个文件夹、CLASSPATH 或 PATH、参数或调用的文件夹中。
右键单击该项目。
- 选择“打开模块设置”
- 将
src
文件夹标记为“源” - 转到编辑配置,然后选择您的主类
- 单击OK或Apply按钮
这对我有用。
另一种让我摸不着头脑的场景是:
package com.me
Public class Awesome extends AwesomeLibObject {
....
public static void main(String[] argv) {
System.out.println("YESS0");
}
}
其中 AwesomeLibObject 是在外部库中定义的类。 我收到了同样令人困惑的错误消息:
Error: Could not find or load main class com.Awesome
解决方法很简单:外部库也必须位于类路径中!
这基本上意味着不存在静态 main(String[] args)
方法。它应该会自动解决它。如果没有,则说明在制作程序(它没有 main 方法)或打包程序(清单信息不正确)时出现了问题。
这有效
public class Hello {
public static void main(String[] args) {
System.out.println("Hello");
}
}
这不起作用
public class Hello {
public Hello() {
System.out.println("Hello");
}
}
Hello
)不包含合适的main
方法,你实际上会得到一个不同异常+消息。所以你的答案甚至与问题不符。
- Stephen C 2022-01-24
修复此问题的最简单方法是在此处重新下载 Maven Apache here: https://maven.apache.org/download.cgi
然后你再次设置你的路径:
系统变量
将路径放在设置 Apache Maven 文件夹的位置,例如:C:\Program Files\apache-maven-3.8.4\bin
重新启动终端或 IDE,它应该可以工作了。
它总是对我有用。
原因#2 - 应用程序的类路径指定不正确。阅读前面链接的三个文档。 (是的...阅读它们!Java 程序员至少了解 Java 类路径机制如何工作的基础知识非常重要。)我想将此文档添加到上面这篇非常好的文章中。
JDK 工具和实用程序 一般信息(文件结构、类路径、类的查找方式、更改) 增强功能(JDK 7 中的增强功能) 标准 JDK 工具和实用程序
https://docs.oracle.com/javase/7/docs/technotes/tools/index.html
https://docs.oracle.com/javase/7/docs/technotes/tools/findingclasses.html
https://docs.oracle.com/javase/7/docs/technotes/tools/windows/classpath.html
Java 启动器如何查找类 了解类路径和包名称
https://docs.oracle.com/javase/7/docs/technotes/tools/solaris/javac.html
Java 中的类加载器 Java 类加载器是 Java 运行时环境的一部分,它将 Java 类动态加载到 Java 虚拟机中。由于类加载器的存在,Java 运行时系统不需要了解文件和文件系统。
Java 类不会一次全部加载到内存中,而是在应用程序需要时才加载到内存中。此时,JRE 调用 Java ClassLoader,这些 ClassLoader 动态地将类加载到内存中。
https://en.wikipedia.org/wiki/Java_Classloader
https://www.geeksforgeeks.org/classloader-in-java/
对于 Java 的新版本,即 Java18,直至 2022 年。 您只需编写 package 关键字以及包含 java 扩展文件和分号的文件夹名称,如下所示:
package JavaProgramming;
因为我在JavaProgramming文件中有hello.java文件。 注意:在为 java 编写文件夹名称时切勿给出空格。就像Java 编程一样,你必须保持这样的状态: JavaProgramming等;
一个简单的hello world的整个代码结构如下:
package JavaProgramming;
public class hello {
public static void main(String[] args) {
System.out.println("Hello java after long time");
}
}
关于外部库的回答 -
编译:
javac -cp ./<external lib jar>: <program-name>.java
执行:
java -cp ./<external lib jar>: <program-name>
上述方案在 OS X 和 Linux 系统中运行良好。注意类路径中的:
。
对于数据库连接,我得到了这个。我刚刚在类路径中添加了以下内容:
export CLASSPATH=<path>/db2jcc4.jar:**./**
在这里,我在最后附加了 ./ ,以便我的类在加载时也能被识别。
现在只需运行:
java ConnectionExample <args>
它工作得很好。
如果您的包名称为 javatpoint,包名称为 com.javatpoint,类名称为 AnotherOne,则按以下类型编译您的类:
cd C:\Users\JAY GURUDEV\eclipse-workspace\javatpoint\src\com\javatpoint
javac AnotherOne.java
并使用运行这个类
cd C:\Users\JAY GURUDEV\eclipse-workspace\javatpoint\src
java com.javatpoint.AnotherOne
(此处应排除包名称。)
这就是我解决问题的方法。
我注意到,如果您在编译中包含 jar 文件,将当前目录 (./) 添加到类路径会有所帮助。
javac -cp "abc.jar;efg.jar" MyClass.java
java -cp "abc.jar;efg.jar" MyClass
与
javac -cp "**./**;abc.jar;efg.jar" MyClass.java<br>
java -cp "**./**;abc.jar;efg.jar" MyClass
排除以下文件解决了问题。
META-INF/*.SF
META-INF/*.DSA
META-INF/*.RSA
在build.gradle
中添加以下代码
jar {
from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
}
{
exclude "META-INF/*.SF"
exclude "META-INF/*.DSA"
exclude "META-INF/*.RSA"
}
manifest {
attributes(
'Main-Class': 'mainclass'
)
}
}