“无法找到或加载主类”是什么意思?

新Java开发人员遇到的一个常见问题是,他们的程序无法运行并显示错误消息: Could not find or load main class ...

这是什么意思,是什么导致它,你应该如何解决它?

回答(30)

3 years ago

有时,在您可能尝试过的某些在线编译器中,如果您不编写 public class [Classname] 而只是 class [Classname] ,则会出现此错误 .

3 years ago

在测试Java MongoDB JDBC连接时,我也遇到了类似的错误 . 我认为最好总结一下我的最终解决方案,以便将来任何人都可以直接查看这两个命令,并且可以继续进行 .

假设您位于Java文件和外部依赖项(JAR文件)所在的目录中 .

Compile:

javac -cp mongo-java-driver-3.4.1.jar JavaMongoDBConnection.java
  • -cp - classpath参数;一个接一个地传递所有依赖的JAR文件

    • .java - 这是具有main方法的Java类文件 . sdsd

Run:

java -cp mongo-java-driver-3.4.1.jar: JavaMongoDBConnection
  • 请在所有依赖关系JAR文件结束后观察冒号(Unix)/逗号(Windows)

  • 最后,观察没有任何扩展名的主类名(没有.class或.java)

3 years ago

首先使用此命令设置路径;

set path="paste the set path address"

然后你需要加载程序 . 在存储的驱动器中键入“cd(文件夹名称)”并进行编译 . 例如,如果我的程序存储在D盘上,输入“D:”按回车并键入“cd(文件夹名称)” .

3 years ago

在我的情况下,出现错误是因为我提供了源文件名而不是类名 .

我们需要向解释器提供包含main方法的类名 .

3 years ago

在Java中,当您有时使用java可执行文件从命令行运行JVM并尝试从具有public static 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/

3 years ago

使用此命令:

java -cp . [PACKAGE.]CLASSNAME

示例:如果您的类名是从Hello.java创建的Hello.class,则使用以下命令:

java -cp . Hello

如果你的文件Hello.java在包com.demo中,那么使用下面的命令

java -cp . com.demo.Hello

对于JDK 8,很多时候类文件存在于同一文件夹中,但 java 命令需要classpath,因此我们添加 -cp . 以将当前文件夹作为classpath的参考 .

3 years ago

根据错误消息(“找不到或加载主类”),有两类问题:

  • 主要课程不能 found

  • 主类不能 loaded (此案例未在接受的答案中详细讨论)

当有 typo or wrong syntax in the fully qualified class namedoes not exist in the provided classpath 时,主类不能 found .

the class cannot be initiated 时,主类不能 loaded ,通常主类扩展另一个类,并且该类在提供的类路径中不存在 .

例如:

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

如果未包含camel-spring,则会报告此错误 .

3 years ago

这里的所有答案都是针对Windows用户的 . 对于Mac,类路径分隔符为 : ,而不是 ; . 作为错误设置,不会抛出使用 ; 的类路径,如果从Windows到Mac,这可能很难发现 .

这是相应的Mac命令:

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

在此示例中,包是 com.test ,并且 lib 文件夹也包含在类路径中 .

3 years ago

好吧,很多答案已经,但没有人提到文件许可可能是罪魁祸首的情况 . 运行用户时无权访问jar文件或路径的某个目录 . 例如考虑:

jar文件在 /dir1/dir2/dir3/myjar.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仍然会发生错误

3 years ago

如果您的main方法位于包下的类中,则应该在层次结构目录上运行它 .

假设有一个源代码文件(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 .

3 years ago

java <class-name>命令语法

首先,您需要了解使用 java (或 javaw )命令启动程序的正确方法 .

正常的syntax1是这样的:

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 方法 . (注意,方法参数的名称是 NOT 签名的一部分 . )

  • 调用该方法将命令行参数("fred","joe","bert")作为 String[] 传递给它 .

Java无法找到该类的原因

当您收到消息"Could not find or load main class ..."时,表示第一步失败 . java 命令无法找到该类 . 实际上,消息中的"..."将是 java 正在寻找的完全限定的类名 .

那么为什么它无法找到 class 呢?

Reason#1 - 你在classname参数中犯了一个错误

第一个可能的原因是您可能提供了错误的类名 . (或者......正确的类名,但形式错误 . )考虑到上面的例子,这里有各种 wrong ways 来指定类名:

  • 示例#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 - 您完全忘记了 class 名称
java lots of arguments

原因#2 - 未正确指定应用程序的类路径

第二个可能的原因是类名是正确的,但是 java 命令找不到类 . 要理解这一点,您需要了解"classpath"的概念 . Oracle文档很好地解释了这一点:

所以......如果你已经正确指定了类名,那么接下来要检查的是你已经正确地指定了类路径:

  • 阅读上面链接的三个文件 . (是的......阅读它们 . 重要的是,Java程序员至少要了解Java类路径机制的工作原理 . )

  • 查看运行 java 命令时生效的命令行和/或CLASSPATH环境变量 . 检查目录名称和JAR文件名是否正确 .

  • 如果类路径中存在相对路径名,请检查它们是否正确解析...从运行 java 命令时生效的当前目录 .

  • 检查类(在错误消息中提到)是否可以位于有效的类路径上 .

  • 请注意,Windows与Linux和Mac OS的类路径语法不同 . (类路径分隔符在Windows上为 ; ,在其他分区上为 : . )

Reason#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

笔记:

  • 在大多数Java版本中, -classpath 选项可以缩短为 -cp . 检查 java 的相应手册条目, javac 等等 .

  • 在类路径中选择绝对路径名和相对路径名时要仔细考虑 . 请记住,如果当前目录更改,则相对路径名可能为"break" .

Reason#2c - 类路径中缺少依赖项

类路径需要包含应用程序所依赖的所有其他(非系统)类 . (系统类是自动定位的,你很少需要关注它 . )为了正确加载主类,JVM需要找到:

(注意:JLS和JVM规范允许JVM的某些范围“懒惰地”加载类,这可能会影响何时抛出类加载器异常 . )

原因#3 - 该类已在错误的包中声明

偶尔会有人将源代码文件放入其源代码树中的错误文件夹中,或者他们遗漏了 package 声明 . 如果在IDE中执行此操作,IDE的编译器将立即告诉您 . 同样,如果您使用一个不错的Java构建工具,该工具将以检测问题的方式运行 javac . 但是,如果您手动构建Java代码,则可以通过编译器不会注意到问题的方式执行此操作,并且生成的".class"文件不在您期望的位置 .

还是找不到问题?

有很多东西要检查,很容易错过一些东西 . 尝试将 -Xdiag 选项添加到 java 命令行(作为 java 之后的第一件事) . 它将输出关于类加载的各种内容,这可以为您提供有关真正问题的线索 .

另外,请考虑从网站,文档等复制和粘贴不可见或非ASCII字符可能导致的问题 . 并考虑“同性恋”,两个字母或符号看起来相同......但不是 .


java -jar <jar文件>语法

用于“可执行”JAR文件的替代语法如下:

java [ <option> ... ] -jar <jar-file-name> [<argument> ...]

例如

java -Xmx100m -jar /usr/local/acme-example/listuser.jar fred

在这种情况下,入口点类的名称(即 com.acme.example.ListUser )和类路径在JAR文件的MANIFEST中指定 .


IDE

典型的Java IDE支持在IDE JVM本身或子JVM中运行Java应用程序 . 这些通常不受此特定异常的影响,因为IDE使用自己的机制来构造运行时类路径,标识主类并创建 java 命令行 .

但是,如果您在IDE后面执行操作,则仍可能发生此异常 . 例如,如果您之前在Eclipse中为Java应用程序设置了应用程序启动器,然后在不告知Eclipse的情况下将包含"main"类的JAR文件移动到文件系统中的其他位置,则Eclipse将无意中启动JVM不正确的类路径 .

简而言之,如果您在IDE中遇到此问题,请检查旧的IDE状态,损坏的项目引用或损坏的启动程序配置等内容 .

IDE也可能简单地混淆 . IDE是非常复杂的软件,包含许多交互部分 . 其中许多部分采用了各种缓存策略,以使IDE作为一个整体响应 . 这些有时可能会出错,一种可能的症状是启动应用程序时出现问题 . 如果您怀疑可能发生这种情况,则值得重新启动IDE .


其他参考文献

3 years ago

当相同的代码在一台PC上工作,但它在另一台PC上显示错误时,我发现的最佳解决方案是编译如下:

javac HelloWorld.java
java -cp . HelloWorld

3 years ago

enter image description here

Class file location: C:\ test \ com \ company

File Name: Main.class

Fully qualified class name: com.company.Main

Command line command:

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

请注意,类路径不包括\ com \ company

3 years ago

在这种情况下我遇到了这样的错误:

java -cp lib.jar com.mypackage.Main

它适用于Windows的 ; 和适用于Unix的 :

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

3 years ago

在Windows上,将 .; 放在CLASSPATH值的开头 .

这个 . (点)表示“查看当前目录” . 这是一个永久的解决方案 .

您也可以使用set CLASSPATH=%CLASSPATH%;. 将其设置为"one time" . 只要您的cmd窗口打开,这将持续 .

3 years ago

你真的需要从 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

3 years ago

解决我的问题的原因是:

右键单击要运行的项目/类,然后单击 Run As - > Run Configurations . 然后你应该修复现有配置或以下列方式添加新配置:

打开 Classpath 选项卡,单击 Advanced... 按钮,然后添加项目的 bin folder .

3 years ago

在这种情况下,你有:

无法找到或加载主类?classpath

这是因为您使用的是"-classpath",但破折号与命令提示符下 java 使用的破折号不同 . 我有这个问题从Notepad复制和粘贴到cmd .

3 years ago

如果使用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>

3 years ago

如果您的情况与我的情况特别相似,这可能对您有所帮助:作为初学者,当我尝试运行Java程序时,我也遇到了这个问题 .

我编译它像这样:

javac HelloWorld.java

我也尝试使用相同的扩展名运行:

java Helloworld.java

当我删除了 .java 并重写了 java HelloWorld 之类的命令时,程序运行得很好 . :)

3 years ago

在我的情况下,我得到了错误,因为我在Windows 7系统上混合了大写和小写包名称 . 将包名称更改为全部小写可解决此问题 . 另请注意,在此方案中,我没有将.java文件编译为.class文件时出错;它只是不会从相同的(子子)子目录运行 .

3 years ago

使用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正确处理类路径参数 .

3 years ago

如果您的类在包中,则必须 cd 到主目录并使用类的全名运行(packageName.MainClassName) .

例:

我的课程在这里:

D:\project\com\cse\

我的主要课程的全名是:

com.cse.Main

所以我 cd 回到主目录:

D:\project

然后发出 java 命令:

java com.cse.Main

3 years ago

我花了相当多的时间试图解决这个问题 . 我以为我是以某种方式错误地设置我的类路径,但问题是我键入:

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

代替:

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

我认为完全限定的含义意味着包括完整的路径名而不是完整的包名 .

3 years ago

如果您的源代码名称是HelloWorld.java,则编译的代码将为 HelloWorld.class .

如果您使用以下方法调用它,您将收到该错误:

java HelloWorld.class

相反,使用这个:

java HelloWorld

3 years ago

试试 -Xdiag .

Steve C's answer很好地涵盖了可能的情况,但有时确定无法找到或加载类可能不那么容易 . 使用 java -Xdiag (自JDK 7起) . 这会打印出一个很好的堆栈跟踪,它提供了消息 Could not find or load main class 消息的含义 .

例如,它可以指向主类使用的其他类,这些类无法找到并阻止加载主类 .

3 years ago

有时可能导致问题的原因与主要课程无关,我必须以艰难的方式找到它 . 它是我移动的引用库,它给了我:

无法找到或加载主类xxx Linux

我刚刚删除了该引用,再次添加它,它再次正常工作 .

3 years ago

我有一个奇怪的 .

错误:无法找到或加载主类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>

一旦我解决了pom relativePath,错误就消失了 .

去搞清楚 .

3 years ago

这是一个特例,但由于我来到这个页面寻找解决方案而没有找到它,我会在这里添加它 .

Windows(使用7测试)不接受类和包名称中的特殊字符(如 á ) . 不过Linux确实如此 .

当我在NetBeans中构建 .jar 并尝试在命令行中运行它时,我发现了这一点 . 它在NetBeans中运行,但不在命令行中运行 .

3 years ago

帮助我的是在命令行上指定类路径,例如:

  • 创建一个新文件夹, 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!