我该如何解决ClassNotFoundException错误?

163

我试图运行一个Java应用程序,但是遇到了这个错误:

java.lang.ClassNotFoundException:

冒号后面跟着缺失的类所在的位置。然而,我知道该位置不存在,因为该类位于其他地方。我如何更新该类的路径?与类路径有关吗?


2
你必须将缺失类的jar文件添加到类路径中。 - Crom
如果你的类有一个包,那么请进入包含该类的文件夹。例如,如果包名为test.abc,则先进入test文件夹,然后执行java -cp . test.abc.CLASSNAME(不需要加上.class后缀)。如果没有包,则直接进入包含该类的文件夹,然后执行java -cp . CLASSNAME。 - Optional
可能是某个类没有被部署到您的运行时环境中(例如缺少jar包),或者该类在给定的类加载器中不可见。请使用此工具对这些问题进行故障排除:http://jhades.org - Angular University
7
有时我也会遇到这种情况。这个异常明显违反了在异常消息中说明所有必要上下文的规则。它应该提到在哪里尝试查找该项,你的类路径上有什么。请改进异常消息。不要让我们去寻找可以帮助解决问题的信息。 - masterxilo
我不知道你是否犯了和我一样的愚蠢错误,但是在运行java ClassName.class时,请改为运行java ClassName。有时候自动补全会给出.\ClassName,请将其中的.\删除。 - Jerry wu
29个回答

68

类路径是一组用于加载类的位置。

这些“位置”可以是目录或者jar文件。

对于目录,JVM将遵循一种预期模式来加载类。如果我的类路径中有目录C:/myproject/classes,并且我尝试加载一个名为com.mycompany.Foo的类,则会在classes目录下查找一个名为com的目录,然后在该目录下查找一个名为mycompany的目录,并最终在那个目录中查找名为Foo.class的文件。

在第二种情况下,对于jar文件,它将在jar文件中搜索该类。实际上,jar文件只是像上面那样的一堆目录的压缩集合。如果解压缩一个jar文件,你会得到一堆目录和遵循上述模式的类文件。

因此,当JVM尝试加载类定义时,它会从头到尾遍历类路径以查找类的定义。例如,在类路径:

C:/myproject/classes;C:/myproject/lib/stuff.jar;C:/myproject/lib/otherstuff.jar

JVM将首先尝试查找目录classes,然后在stuff.jar中查找,最后在otherstuff.jar中查找。

当你遇到ClassNotFoundException时,这意味着JVM已经遍历了整个类路径并且没有找到你尝试引用的类。解决方案通常是检查你的类路径,这在Java世界中是很常见的。

你可以通过在命令行中输入java -cp,然后输入你的类路径来定义一个类路径。在IDE(例如Eclipse)中,你会有一个菜单选项来指定你的类路径。


45
你的类路径出现了问题(这在Java世界中非常常见)。根据你启动应用程序的方式,你需要修改-cp参数、MANIFEST.MF中的Class-Path条目或者磁盘布局。

45
你能不能更加具体地说明与 Eclipse 相关的内容?我需要做些什么? - user2426316
34
你的问题中缺少足够的信息,无法提供更具体的答案。请考虑补充相关信息。 - Thorbjørn Ravn Andersen
2
我只是强调除了Java世界之外,所有软件都需要确保找到正确版本的依赖关系。我可以举出dll-hell、包管理器、版本管理器、Spring Boot材料清单和Docker容器作为这个问题和可能解决方案的例子。外部代码所占比例越大,问题就越大。 - masterxilo
@bikeman868 Java类路径可能是你在阅读Java语言时遇到的第一个非平凡的问题,而且每个人都会遇到问题,你绝对需要理解它才能进步。这个旧答案无法说明有什么问题(因此如何修复),因为问题没有包含足够的信息。请考虑打开一个新问题,仔细解释你的问题。 - Thorbjørn Ravn Andersen
1
@bikeman868,您在抱怨这个十年前的答案明确说明了什么出了问题,而且OP没有提供足够的信息来得到更好的答案,对于您有一个完全不同的问题来说并不有用。很抱歉。这个网站上存在许多更好的回答和更好的问题。我再次建议您打开自己的问题,准确地解释您的问题,因为那很可能会给您一个适合您现在所处位置的答案。 - Thorbjørn Ravn Andersen
显示剩余5条评论

23

到目前为止,这是我发现的最佳解决方案

假设我们有一个名为org.mypackage的包,其中包含以下类:

  • HelloWorld(主类)
  • SupportClass
  • UtilClass

并且定义此包的文件在物理上存储在目录D:\myprogram(在Windows上)或/home/user/myprogram(在Linux上)下。

文件结构如下所示: enter image description here

当我们调用Java时,我们指定要运行的应用程序的名称:org.mypackage.HelloWorld。但是,我们还必须告诉Java在哪里查找定义我们的包的文件和目录。因此,要启动程序,我们必须使用以下命令: enter image description here

注意:无论您当前的位置在哪里,都必须执行上述java命令。但是对于javac,情况并非如此。为了编译,您甚至可以直接进入具有您的.java文件的目录,并直接执行javac ClassName.java


11
如果您知道类的路径或包含类的JAR文件的路径,则在运行时将其添加到您的类路径中。您可以使用此处提到的类路径:
在Windows上
java -classpath .;yourjar.jar YourMainClass

在UNIX/Linux操作系统上

java -classpath .:yourjar.jar YourMainClass

10
我遇到了同样的错误,花费了整整一天才意识到这是一个依赖冲突的问题:
- 我导入了两个库,A 和 B; - A 和 B 都依赖于另一个库 C,但是是不同版本的 C。比如说,A 依赖于 C 1.0,而 B 依赖于 C 2.0; - B 使用了一个只存在于 C 2.0 中的类; - 但是,A 在依赖树中更“接近”,所以 Maven 对 A 和 B 都使用了 C 1.0,并且甚至没有警告你(对我来说这真是太惊人了); - 结果是,当 B 尝试使用仅存在于 C 2.0 中的类时,会抛出 ClassNotFoundException 异常;
现在奇怪的是:如果你在 IDE 中浏览 B 的代码,并尝试跳转到仅存在于 C 2.0 中的类,它可以正确工作。C 2.0 确实已安装并且你的 IDE 也知道它,但运行应用程序时会被忽略。
这真的让我发疯了…
最终我不得不将 C 2.0 添加到我的 pom.xml 中,以便它可以优先选择 C 1.0。
请参考此帖子了解 Maven 如何选择最近的依赖项:https://dev59.com/fl8f5IYBdhLWcg3wK__4#63815140 你可以使用 mvn dependency:tree 命令可视化依赖树。

4
到目前为止,这是最有用的答案,因为它很好地解释了一个常见的现实情况,而不仅仅是像大多数其他答案一样机械地重复“检查你的类路径”。 - Akito

4
如果您使用maven,请尝试以下方法。我在我的项目中使用maven,当我执行mvn clean install并尝试运行程序时,会抛出异常。因此,我清理项目并再次运行它,这样它就可以正常工作。
我使用eclipse IDE。
如果在运行Junit测试时出现“类未找到”异常,请尝试运行mvn clean test一次。它将编译所有测试类。

当你运行“mvn clean test”命令时,你在哪个目录下?它是否与POM文件在同一个目录下? - TacoB0t
2
是的。从pom文件所在的目录运行它。 - Arun

4

基础通用问题 - 最简单的通用答案 ;)

根据信息,我假设您可能正在尝试基本的编码方法,使用一些简单的文本编辑器和一些命令行工具来构建/编译和运行一个简单的控制台应用程序,例如“Hello World”。

此错误发生在以下情况下:

..\SomePath>javac HelloWorld.java
..\SomePath>java HelloWorld.class

换句话说,使用:

..\SomePath>java HelloWorld

附加文件扩展名 .class 会产生相同的错误。同时,请确保将 Java(JDK/JRE)的 bin 文件夹添加到操作系统的环境变量 PATH 中。(查找更多详细信息,请参阅其他帖子)

另外,我的假设/推断是否正确?


4
如果您使用maven,请检查您的pom.xml中是否有此插件:
    <build>
        <plugins>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>3.2.0</version>
                <executions>
                    <!-- Attach the shade goal into the package phase -->
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

        </plugins>
    </build>

这将把你的依赖项(异常原因)放入你的jar包中。

FYI: 这将包括最终jar包中膨胀的所有依赖项。


3
将jar文件的完整路径添加到CLASSPATH中。 在Linux系统中使用:export CLASSPATH=".:/full/path/to/file.jar:$CLASSPATH"。另一种方法是将jar文件解压缩到当前项目文件夹中,而不需要编辑CLASSPATH,此方法同样可行。 以下方法对我无效: 1)使用带有jar文件完整路径的-cp选项。 2)当位于当前文件夹中时,仅使用jar名称的-cp选项。 3)将jar文件复制到当前项目文件夹中。 4)将jar文件复制到Java jar的标准位置(/usr/share/java)中。 此解决方案适用于mysql-connector-java.5-*.jar中的com.mysql.jdbc.Driver类,在OpenJDK 1.7版本的Linux系统上有效。

只有解压JAR文件对我有效,其他的解决方案都没有用。 - OverCoder

3

通过命令行将类的位置添加到类路径中,只需在运行时添加-cp-classpath和类的位置。例如:

java -cp "c:/location/of/file" YourProgram

如果您正在运行像eclipse这样的IDE,您可以右键单击项目 -> 构建路径 -> 配置构建路径 并将包含您的类的外部JAR添加到构建路径中,然后它应该能够正常工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接