新 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
的编译版本类(class)。 main
带有签名、返回类型和修饰符的方法由 public static void main(String[])
给出. (注意,方法参数的名称是 不是 签名的一部分。)String[]
传递给它. Java找不到类的原因
当您收到“Could not find or load main class ...”消息时,这意味着第一步失败了。
java
命令无法找到该类。实际上,消息中的“...”将是java
的完全限定类名。在寻找。那么为什么可能找不到类呢?
原因 #1 - 你在 classname 参数上犯了一个错误
第一个可能的原因是您可能提供了错误的类名。 (或者……正确的类名,但形式错误。)考虑到上面的例子,这里有各种 错误的方式 指定类名:
java ListUser
当类在包中声明时,例如 com.acme.example
,那么您必须使用完整的类名,包括 java
中的包名。命令;例如java com.acme.example.ListUser
java ListUser.class
java com/acme/example/ListUser.class
java com.acme.example.listuser
java com.acme.example.mistuser
java ListUser.java
java lots of arguments
原因 #2 - 应用程序的类路径指定不正确
第二个可能的原因是类名是正确的,但
java
命令找不到类。要理解这一点,您需要了解“类路径”的概念。 Oracle 文档对此进行了很好的解释:java
command documentation 所以......如果你正确指定了类名,接下来要检查的是你是否正确指定了类路径:
java
时生效的 CLASSPATH 环境变量。命令。检查目录名和 JAR 文件名是否正确。 java
时生效的当前目录。命令。 ;
,在其他系统上是 :
。如果你的平台使用了错误的分隔符,你不会得到明确的错误消息。相反,你会得到一个不存在的文件或目录将被默默忽略的路径。)原因 #2a - 错误的目录在类路径上
当您在类路径上放置一个目录时,它理论上对应于限定 namespace 的根。通过将完全限定名称映射到路径名,类位于该根目录下的目录结构中。因此,例如,如果“/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 不匹配
如果您的类(class) FQN 是
com.acme.example.Foon
,然后JVM将在目录“com/acme/example”中寻找“Foon.class”:Caused by: java.lang.NoClassDefFoundError: <path> (wrong name: <name>)
因为类文件中的 FQN 与类加载器期望找到的不匹配。举一个具体的例子,假设:
com.acme.example.Foon
类(class),/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
等等。 原因 #2c - 类路径中缺少依赖项
类路径需要包含您的应用程序依赖的所有其他(非系统)类。 (系统类是自动定位的,你很少需要关心这个。)为了正确加载主类,JVM 需要找到:
(注意:JLS 和 JVM 规范允许 JVM 在一定范围内“延迟地”加载类,这会影响类加载器异常何时抛出。)
原因 #3 - 该类已在错误的包中声明
偶尔会发生有人将源代码文件放入
在他们的源代码树中错误的文件夹,或者他们遗漏了
package
宣言。如果您在 IDE 中执行此操作,IDE 的编译器会立即告诉您有关情况。同样,如果您使用一个不错的 Java 构建工具,该工具将运行 javac
以一种能够检测到问题的方式。但是,如果您手动构建 Java 代码,那么编译器不会注意到问题,并且生成的“.class”文件不在您期望的位置。还是找不到问题?
有很多东西要检查,很容易错过一些东西。尝试添加
-Xdiag
java
的选项命令行(作为 java
之后的第一件事)。它将输出有关类加载的各种信息,这可能会为您提供有关真正问题所在的线索。此外,请考虑从网站、文档等中复制和粘贴不可见或非 ASCII 字符可能导致的问题。并考虑“同形文字”,其中两个字母或符号看起来相同……但并非如此。
最后,如果您尝试从
(META-INF/*.SF)
中签名不正确的 JAR 文件启动,显然会遇到此问题。或者如果 MANIFEST.MF
中存在语法错误文件(见 https://stackoverflow.com/a/67145190/139985)。java
的替代语法使用
java command
启动 Java 程序有三种替代语法。 .java [ <options> ] -jar <jar-file-name> [<arg> ...]
例如java -Xmx100m -jar /usr/local/acme-example/listuser.jar fred
入口点类的名称(即 com.acme.example.ListUser
)和类路径在 JAR 文件的 MANIFEST 中指定。java [ <options> ] --module <module>[/<mainclass>] [<arg> ...]
入口点类的名称由 <module>
定义。本身,或者由可选的 <mainclass>
给出.java [ <options> ] <sourcefile> [<arg> ...]
哪里<sourcefile>
是(通常)后缀为“.java”的文件。更多详情请引用
java
的官方文档您正在使用的 Java 版本的命令。集成开发环境
典型的 Java IDE 支持在 IDE JVM 本身或子 JVM 中运行 Java 应用程序。这些通常不受此特定异常的影响,因为 IDE 使用自己的机制来构建运行时类路径、识别主类并创建
java
。命令行。但是,如果您在 IDE 背后进行操作,则仍有可能发生此异常。例如,如果您之前在 Eclipse 中为您的 Java 应用程序设置了一个应用程序启动器,然后您将包含“主”类的 JAR 文件移动到文件系统中的不同位置,而没有告诉 Eclipse,Eclipse 将在不知不觉中启动 JVM使用不正确的类路径。
简而言之,如果您在 IDE 中遇到此问题,请检查诸如过时的 IDE 状态、损坏的项目引用或损坏的启动器配置等内容。
IDE 也可能会感到困惑。 IDE 是由许多交互部分组成的极其复杂的软件。其中许多部分采用了各种缓存策略,以使 IDE 作为一个整体进行响应。这些有时会出错,一种可能的症状是启动应用程序时出现问题。如果您怀疑这可能发生,值得尝试其他方法,例如重新启动 IDE、重建项目等。
其他引用
关于java - "Could not find or load main class"是什么意思?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18093928/