“无法找到或加载主类”是什么意思?
新Java开发人员遇到的一个常见问题是,他们的程序无法运行,并显示错误消息: Could not find or load main class ...
这是什么意思,是什么原因造成的,你应该如何解决?
java <class-name>
命令语法
首先,您需要了解使用java
(或javaw
)命令启动程序的正确方法。
正常的语法1是这样的:
java [ <option> ... ] <class-name> [<argument> ...]
其中<option>
是命令行选项(以“ - ”字符开头), <class-name>
是完全限定的Java类名称, <argument>
是传递给应用程序的任意命令行参数。
1 - 第二种语法是“可执行”JAR文件,我将在后面介绍。
该类的完全限定名称(FQN)通常按照您在Java源代码中的方式编写; 例如
packagename.packagename2.packagename3.ClassName
但是,某些版本的java
命令允许您使用斜线而不是句点; 例如
packagename/packagename2/packagename3/ClassName
(令人困惑的)看起来像一个文件路径名,但不是一个。 请注意,术语“完全限定名称”是标准的Java术语...不是我刚刚制作的让您迷惑的:-)
下面是一个java
命令应该是什么样子的例子:
java -Xmx100m com.acme.example.ListUsers fred joe bert
以上将导致java
命令执行以下操作:
com.acme.example.ListUsers
类的编译版本。 public static void main(String[])
给出的修饰符的main
方法。 (请注意,方法参数的名称不是签名的一部分。) String[]
传递给命令行参数(“fred”,“joe”,“bert”)。 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 ListUser.java
例#6 - 你完全忘记了课程名称
java lots of arguments
原因#2 - 错误地指定了应用程序的类路径
第二个可能的原因是类名是正确的,但是java
命令找不到该类。 要理解这一点,你需要理解“classpath”的概念。 Oracle文档很好地解释了这一点:
java
命令文档 所以......如果你正确地指定了类名,接下来要检查的是你已经正确地指定了classpath:
java
命令时有效的CLASSPATH环境变量。 检查目录名称和JAR文件名是否正确。 java
命令时生效的当前目录中。 原因#2a - 错误的目录位于类路径中
当你把一个目录放在类路径上时,它在概念上与合格名称空间的根对应。 通过将完全限定名称映射到路径名,类位于该根下的目录结构中。 例如,如果类路径中有“/ 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将在目录“com / acme / example”中查找“Foon.class”:
如果您的目录结构与上述模式不匹配,则JVM将找不到您的类。
如果您尝试通过移动它来重命名类,那么也会失败......但异常堆栈跟踪将有所不同。
举一个具体的例子,假设:
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
, javac
等各自的手册条目。 原因#2c - 类路径中缺少依赖关系
类路径需要包含应用程序依赖的所有其他(非系统)类。 (系统类自动定位,并且您很少需要关注这一点。)要正确加载主类,JVM需要查找:
(注意:JLS和JVM规范允许JVM在一定范围内“懒惰”地加载类,这可能会影响抛出类加载器异常的情况。)
原因#3 - 该类已被声明在错误的包中
偶尔会发生某人将源代码文件放入其源代码树中的错误文件夹中,或者他们忽略了package
声明。 如果您在IDE中执行此操作,IDE的编译器会立即告诉您这一点。 同样,如果您使用了体面的Java构建工具,该工具将以检测问题的方式运行javac
。 但是,如果您手动构建Java代码,则可以这样做,即编译器不会注意到问题,并且生成的“.class”文件不在您期望的位置。
java -jar <jar file>
语法
用于“可执行”JAR文件的替代语法如下所示:
java [ <option> ... ] -jar <jar-file-name> [<argument> ...]
例如
java -Xmx100m -jar /usr/local/acme-example/listuser.jar fred
在这种情况下,入口点类的名称(即com.acme.example.ListUser
)和类路径在JAR文件的MANIFEST中指定。
集成开发环境
典型的Java IDE支持在IDE JVM本身或子JVM中运行Java应用程序。 这些通常不受此特定异常的影响,因为IDE使用自己的机制来构造运行时类路径,确定主类并创建java
命令行。
但是,如果您在IDE背后执行操作,则仍有可能发生此异常。 例如,如果您以前在Eclipse中为您的Java应用程序设置了应用程序启动器,然后您在不告知Eclipse的情况下将包含“main”类的JAR文件移动到文件系统中的其他位置,Eclipse会不经意地启动JVM带有不正确的类路径。
简而言之,如果你在IDE中遇到这个问题,请检查诸如陈旧的IDE状态,破坏的项目引用或破坏的启动器配置。
IDE也可能会让人感到困惑。 IDE是非常复杂的软件,由许多相互作用的部分组成。 这些部分中的许多部分都采用了各种缓存策略,以使IDE整体响应。 这些有时可能会出错,并且一个可能的症状是启动应用程序时出现的问题。 如果您怀疑会发生这种情况,值得重新启动IDE。
其他参考
如果您的源代码名称为HelloWorld.java,则您的编译代码将为HelloWorld.class
。
如果您使用以下方式调用它,您将得到该错误:
java HelloWorld.class
相反,使用这个:
java HelloWorld
如果您的类在包中,那么您必须cd
到主目录并使用类的全名(packageName.MainClassName)运行。
例:
我的课程在这里:
D:projectcomcse
我的主类的全名是:
com.cse.Main
所以,我cd
回到主目录:
D:project
然后发出java
命令:
java com.cse.Main
链接地址: http://www.djcxy.com/p/1609.html
上一篇: What does "Could not find or load main class" mean?
下一篇: `if