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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18093928/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 22:20:12  来源:igfitidea点击:

What does "Could not find or load main class" mean?

javaclassmain

提问by Stephen C

A common problem that new Java developers experience is that their programs fail to run with the error message: Could not find or load main class ...

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

What does this mean, what causes it, and how should you fix it?

这是什么意思,是什么原因造成的,你应该如何解决它?

采纳答案by Stephen C

The java <class-name>command syntax

java <class-name>命令语法

First of all, you need to understand the correct way to launch a program using the java(or javaw) command.

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

The normal syntax1is this:

正常的语法1是这样的:

    java [ <options> ] <class-name> [<arg> ...]

where <option>is a command line option (starting with a "-" character), <class-name>is a fully qualified Java class name, and <arg>is an arbitrary command line argument that gets passed to your application.

其中<option>是命令行选项(以“-”字符开头),<class-name>是完全限定的 Java 类名,<arg>是传递给应用程序的任意命令行参数。



1 - There are some other syntaxes which are described near the end of this answer.

1 - 在此答案的末尾附近描述了一些其他语法。

The fully qualified name (FQN) for the class is conventionally written as you would in Java source code; e.g.

类的完全限定名称 (FQN) 通常按照 Java 源代码的方式编写;例如

    packagename.packagename2.packagename3.ClassName

However some versions of the javacommand allow you to use slashes instead of periods; e.g.

然而,该java命令的某些版本允许您使用斜杠而不是句点;例如

    packagename/packagename2/packagename3/ClassName

which (confusingly) looks like a file pathname, but isn't one. Note that the term fully qualified nameis standard Java terminology ... not something I just made up to confuse you :-)

它(令人困惑)看起来像一个文件路径名,但不是一个。请注意,完全限定名称这个术语是标准的 Java 术语......不是我编造出来的东西来迷惑你 :-)

Here is an example of what a javacommand should look like:

下面是一个java命令应该是什么样子的例子:

    java -Xmx100m com.acme.example.ListUsers fred joe bert

The above is going to cause the javacommand to do the following:

以上将导致java命令执行以下操作:

  1. Search for the compiled version of the com.acme.example.ListUsersclass.
  2. Load the class.
  3. Check that the class has a mainmethod with signature, return typeand modifiersgiven by public static void main(String[]). (Note, the method argument's name is NOTpart of the signature.)
  4. Call that method passing it the command line arguments ("fred", "joe", "bert") as a String[].
  1. 搜索com.acme.example.ListUsers类的编译版本。
  2. 加载类。
  3. 检查该类是否具有main带有签名返回类型和由 给出的修饰符的方法public static void main(String[])。(注意,方法参数的名称不是签名的一部分。)
  4. 调用该方法,将命令行参数(“fred”、“joe”、“bert”)作为String[].

Reasons why Java cannot find the class

Java找不到类的原因

When you get the message "Could not find or load main class ...", that means that the first step has failed. The javacommand was not able to find the class. And indeed, the "..." in the message will be the fully qualified class namethat javais looking for.

当您收到“Could not find or load main class ...”消息时,这意味着第一步失败了。该java命令无法找到该类。事实上,在“...”的消息将是完全合格的类名java所期待的。

So why might it be unable to find the class?

那么为什么可能找不到类呢?

Reason #1 - you made a mistake with the classname argument

原因 #1 - 你在 classname 参数上犯了一个错误

The first likely cause is that you may have provided the wrong class name. (Or ... the right class name, but in the wrong form.) Considering the example above, here are a variety of wrong waysto specify the class name:

第一个可能的原因是您可能提供了错误的类名。(或者……正确的类名,但形式错误。)考虑到上面的例子,这里有多种指定类名的错误方法

  • Example #1 - a simple class name:

    java ListUser
    

    When the class is declared in a package such as com.acme.example, then you must use the full classname includingthe package name in the javacommand; e.g.

    java com.acme.example.ListUser
    
  • Example #2 - a filename or pathname rather than a class name:

    java ListUser.class
    java com/acme/example/ListUser.class
    
  • Example #3 - a class name with the casing incorrect:

    java com.acme.example.listuser
    
  • Example #4 - a typo

    java com.acme.example.mistuser
    
  • Example #5 - a source filename (except for Java 11 or later; see below)

    java ListUser.java
    
  • Example #6 - you forgot the class name entirely

    java lots of arguments
    
  • 示例 #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
    

Reason #2 - the application's classpath is incorrectly specified

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

The second likely cause is that the class name is correct, but that the javacommand cannot find the class. To understand this, you need to understand the concept of the "classpath". This is explained wellby the Oracle documentation:

第二个可能的原因是类名正确,但java命令找不到类。要理解这一点,您需要了解“类路径”的概念。Oracle 文档对此进行了很好的解释:

So ... if you have specified the class name correctly, the next thing to check is that you have specified the classpath correctly:

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

  1. Read the three documents linked above. (Yes ... READ them! It is important that a Java programmer understandsat least the basics of how the Java classpath mechanisms works.)
  2. Look at command line and / or the CLASSPATH environment variable that is in effect when you run the javacommand. Check that the directory names and JAR file names are correct.
  3. If there are relativepathnames in the classpath, check that they resolve correctly ... from the current directory that is in effect when you run the javacommand.
  4. Check that the class (mentioned in the error message) can be located on the effectiveclasspath.
  5. Note that the classpath syntax is differentfor Windows versus Linux and Mac OS. (The classpath separator is ;on Windows and :on the others. If you use the wrong separator for your platform, you won't get an explicit error message. Instead, you will get a nonexistent file or directory on the path that will be silently ignored.)
  1. 阅读上面链接的三个文件。(是的...阅读它们!重要的是,Java程序员了解如何在Java类路径机制的作品至少基本资讯)。
  2. 查看命令行和/或运行java命令时生效的 CLASSPATH 环境变量。检查目录名和 JAR 文件名是否正确。
  3. 如果类路径中有相对路径名,请检查它们是否从运行java命令时生效的当前目录中正确解析...。
  4. 检查该类(错误消息中提到的)是否可以位于有效的类路径上。
  5. 请注意,Windows 与 Linux 和 Mac OS的类路径语法不同。(类路径分隔符;在 Windows 和:其他平台上。如果您为您的平台使用了错误的分隔符,您将不会收到明确的错误消息。相反,您将在路径上得到一个不存在的文件或目录,该文件或目录将被静默忽略.)

Reason #2a - the wrong directory is on the classpath

原因 #2a - 错误的目录在类路径上

When you put a directory on the classpath, it notionally corresponds to the root of the qualified name space. Classes are located in the directory structure beneath that root, by mapping the fully qualified name to a pathname. So for example, if "/usr/local/acme/classes" is on the class path, then when the JVM looks for a class called com.acme.example.Foon, it will look for a ".class" file with this pathname:

当您在类路径上放置一个目录时,它理论上对应于限定名称空间的根。通过将完全限定名称映射到路径名,类位于该根目录下的目录结构中。因此,例如,如果“/usr/local/acme/classes”在类路径上,那么当 JVM 查找名为 的类时com.acme.example.Foon,它将查找具有以下路径名的“.class”文件:

  /usr/local/acme/classes/com/acme/example/Foon.class

If you had put "/usr/local/acme/classes/com/acme/example" on the classpath, then the JVM wouldn't be able to find the class.

如果您将“/usr/local/acme/classes/com/acme/example”放在类路径上,那么JVM 将无法找到该类。

Reason #2b - the subdirectory path doesn't match the FQN

原因 #2b - 子目录路径与 FQN 不匹配

If your classes FQN is com.acme.example.Foon, then the JVM is going to look for "Foon.class" in the directory "com/acme/example":

如果您的类 FQN 是com.acme.example.Foon,则 JVM 将在目录“com/acme/example”中查找“Foon.class”:

  • If your directory structure doesn't match the package naming as per the pattern above, the JVM won't find your class.

  • If you attempt renamea class by moving it, that will fail as well ... but the exception stacktrace will be different. It is liable to say something like this:

    Caused by: java.lang.NoClassDefFoundError: <path> (wrong name: <name>)
    

    because the FQN in the class file doesn't match what the class loader is expecting to find.

  • 如果您的目录结构与上述模式中的包命名不匹配,则 JVM 将找不到您的类。

  • 如果您尝试通过移动来重命名类,那也会失败……但异常堆栈跟踪会有所不同。很可能会说这样的话:

    Caused by: java.lang.NoClassDefFoundError: <path> (wrong name: <name>)
    

    因为类文件中的 FQN 与类加载器期望找到的不匹配。

To give a concrete example, supposing that:

举一个具体的例子,假设:

  • you want to run com.acme.example.Foonclass,
  • the full file path is /usr/local/acme/classes/com/acme/example/Foon.class,
  • your current working directory is /usr/local/acme/classes/com/acme/example/,
  • 你想跑com.acme.example.Foon课,
  • 完整的文件路径是/usr/local/acme/classes/com/acme/example/Foon.class
  • 您当前的工作目录是/usr/local/acme/classes/com/acme/example/

then:

然后:

# 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

Notes:

笔记:

  • The -classpathoption can be shortened to -cpin most Java releases. Check the respective manual entries for java, javacand so on.
  • Think carefully when choosing between absolute and relative pathnames in classpaths. Remember that a relative pathname may "break" if the current directory changes.
  • 在大多数 Java 版本中,该-classpath选项可以缩写为-cp。检查相应的手册条目javajavac以此类推。
  • 在类路径中的绝对路径名和相对路径名之间进行选择时要仔细考虑。请记住,如果当前目录发生变化,相对路径名可能会“中断”。

Reason #2c - dependencies missing from the classpath

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

The classpath needs to include all of the other(non-system) classes that your application depends on. (The system classes are located automatically, and you rarely need to concern yourself with this.) For the main class to load correctly, the JVM needs to find:

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

(Note: the JLS and JVM specifications allow some scope for a JVM to load classes "lazily", and this can affect when a classloader exception is thrown.)

(注意:JLS 和 JVM 规范允许 JVM 在一定范围内“延迟地”加载类,这会影响类加载器异常何时抛出。)

Reason #3 - the class has been declared in the wrong package

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

It occasionally happens that someone puts a source code file into the the wrong folder in their source code tree, or they leave out the packagedeclaration. If you do this in an IDE, the IDE's compiler will tell you about this immediately. Similarly if you use a decent Java build tool, the tool will run javacin a way that will detect the problem. However, if you build your Java code by hand, you can do it in such a way that the compiler doesn't notice the problem, and the resulting ".class" file is not in the place that you expect it to be.

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

Still can't find the problem?

还是找不到问题?

There lots of things to check, and it is easy to miss something. Try adding the -Xdiagoption to the javacommand line (as the first thing after java). It will output various things about class loading, and this may offer you clues as to what the real problem is.

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

Also, consider possible problems caused by copying and pasting invisible or non-ASCII characters from websites, documents and so on. And consider "homoglyphs", were two letters or symbols look the same ... but aren't.

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

Finally, you can apparently run into this problem if you try to launch from a JAR file with incorrect signatures in (META-INF/*.SF).

最后,如果您尝试从带有不正确签名的 JAR 文件启动(META-INF/*.SF).



Alternative syntaxes for java

替代语法 java

There are three alternative syntaxes for the launching Java programs using the java command.

使用java command.

1) The syntax used for launching an "executable" JAR file is as follows:

1) 用于启动“可执行”JAR 文件的语法如下:

  java [ <options> ] -jar <jar-file-name> [<arg> ...]

e.g.

例如

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

The name of the entry-point class (i.e. com.acme.example.ListUser) and the classpath are specified in the MANIFEST of the JAR file.

入口点类的名称(即com.acme.example.ListUser)和类路径在 JAR 文件的 MANIFEST 中指定。

2) The syntax for launching an application from a module (Java 9 and later) is as follows:

2) 从模块(Java 9 及更高版本)启动应用程序的语法如下:

  java [ <options> ] --module <module>[/<mainclass>] [<arg> ...]

The name of the entrypoint class is either defined by the <module>itself, or is given by the optional <mainclass>.

入口点类的名称要么由其<module>自身定义,要么由可选的<mainclass>.

3) From Java 11 onwards, you can compile and run a single source code file and run it with the following syntax:

3) 从 Java 11 开始,您可以编译和运行单个源代码文件,并使用以下语法运行它:

  java [ <options> ] <sourcefile> [<arg> ...]

where is (typically) a file with the suffix ".java".

哪里是(通常)带有后缀“.java”的文件。

For more details, please refer to the official documentation for the javacommand for the Java release that you are using.

有关更多详细信息,请参阅java您使用的 Java 版本的命令的官方文档。



IDEs

集成开发环境

A typical Java IDE has support for running Java applications in the IDE JVM itself or in a child JVM. These are generallyimmune from this particular exception, because the IDE uses its own mechanisms to construct the runtime classpath, identify the main class and create the javacommand line.

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

However it is still possible for this exception to occur, if you do things behind the back of the IDE. For example, if you have previously set up an Application Launcher for your Java app in Eclipse, and you then moved the JAR file containing the "main" class to a different place in the file system without telling Eclipse, Eclipse would unwittingly launch the JVM with an incorrect classpath.

但是,如果您在 IDE 背后进行操作,则仍有可能发生此异常。例如,如果您之前在 Eclipse 中为您的 Java 应用程序设置了一个应用程序启动器,然后您将包含“主”类的 JAR 文件移动到文件系统中的不同位置,而没有告诉 Eclipse,Eclipse 将在不知不觉中启动 JVM使用不正确的类路径。

In short, if you get this problem in an IDE, check for things like stale IDE state, broken project references or broken launcher configurations.

简而言之,如果您在 IDE 中遇到此问题,请检查诸如过时的 IDE 状态、损坏的项目引用或损坏的启动器配置等内容。

It is also possible for an IDE to simply get confused. IDE's are hugely complicated pieces of software comprising many interacting parts. Many of these parts adopt various caching strategies in order to make the IDE as a whole responsive. These can sometimes go wrong, and one possible symptom is problems when launching applications. If you suspect this could be happening, it is worth trying other things like restarting your IDE, rebuilding the project and so on.

IDE 也可能会感到困惑。IDE 是由许多交互部分组成的极其复杂的软件。其中许多部分采用了各种缓存策略,以使 IDE 作为一个整体进行响应。这些有时会出错,一种可能的症状是启动应用程序时出现问题。如果您怀疑这可能发生,值得尝试其他方法,例如重新启动 IDE、重建项目等。



Other References

其他参考

回答by Eduardo Dennis

Sometimes what might be causing the issue has nothing to do with the main class, and I had to find this out the hard way. It was a referenced library that I moved, and it gave me the:

有时可能导致问题的原因与主类无关,我不得不费力地找出这一点。这是我移动的参考库,它给了我:

Could not find or load main class xxx Linux

无法找到或加载主类 xxx Linux

I just deleted that reference, added it again, and it worked fine again.

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

回答by arun

First set the path using this command;

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

set path="paste the set path address"

Then you need to load the program. Type "cd (folder name)" in the stored drive and compile it. For Example, if my program stored on the D drive, type "D:" press enter and type " cd (folder name)".

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

回答by KawaiKx

In my case, error appeared because I had supplied the source file name instead of the class name.

就我而言,出现错误是因为我提供了源文件名而不是类名。

We need to supply the class name containing the main method to the interpreter.

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

回答by panoet

If your source code name is HelloWorld.java, your compiled code will be HelloWorld.class.

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

You will get that error if you call it using:

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

java HelloWorld.class

Instead, use this:

相反,使用这个:

java HelloWorld

回答by Celebes

What helped me was specifying the classpath on the command line, for example:

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

  1. Create a new folder, C:\temp

  2. Create file Temp.java in C:\temp, with the following class in it:

    public class Temp {
        public static void main(String args[]) {
            System.out.println(args[0]);
        }
    }
    
  3. Open a command line in folder C:\temp, and write the following command to compile the Temp class:

    javac Temp.java
    
  4. Run the compiled Java class, adding the -classpathoption to let JRE know where to find the class:

    java -classpath C:\temp Temp Hello!
    
  1. 新建一个文件夹, C:\temp

  2. 在 中创建文件 Temp.java C:\temp,其中包含以下类:

    public class Temp {
        public static void main(String args[]) {
            System.out.println(args[0]);
        }
    }
    
  3. 在文件夹中打开命令行C:\temp,编写如下命令编译Temp类:

    javac Temp.java
    
  4. 运行编译的 Java 类,添加-classpath选项让 JRE 知道在哪里可以找到该类:

    java -classpath C:\temp Temp Hello!
    

回答by M-Razavi

If you define the main class and main method in a package, you should run it over the hierarchical directory, using the full name of the class (packageName.MainClassName).

如果在 a 中定义主类和主方法package,则应使用类的全名 ( packageName.MainClassName)在分层目录中运行它。

Assume there is a source code file (Main.java):

假设有一个源代码文件(Main.java):

package com.test;

public class Main {

    public static void main(String[] args) {
        System.out.println("salam 2nya\n");
    }
}

For running this code, you should place Main.Classin the package like directory ./com/test/Main.Java. And in the root directory use java com.test.Main.

要运行此代码,您应该将其放置Main.Class在类似目录的包中./com/test/Main.Java。并在根目录中使用java com.test.Main.

回答by tharinduwijewardane

If your classes are in packagesthen you have to cdto the root directory of your project and run using the fully qualified name of the class (packageName.MainClassName).

如果您的类在包中,那么您必须到cd项目的根目录并使用类的完全限定名称 (packageName.MainClassName) 运行。

Example:

例子:

My classes are in here:

我的课在这里:

D:\project\com\cse\

The fully qualified name of my main class is:

我的主类的完全限定名称是:

com.cse.Main

So I cdback to the root project directory:

所以我cd回到项目根目录:

D:\project

Then issue the javacommand:

然后发出java命令:

java com.cse.Main

This answer is for rescuing newbie java programmers from the frustration caused by a common mistake, I recommend you read the accepted answer for more in depth knowledge about the java classpath.

这个答案是为了使新手 Java 程序员免于因常见错误而感到沮丧,我建议您阅读已接受的答案以获取有关 Java 类路径的更深入的知识。

回答by Nathan Williams

In this instance you have:

在这种情况下,您有:

Could not find or load main class ?classpath

无法找到或加载主类?classpath

It's because you are using "-classpath", but the dash is not the same dash used by javaon the command prompt. I had this issue copying and pasting from Notepadto cmd.

这是因为您使用的是“-classpath”,但破折号java与命令提示符上使用的破折号不同。我在从记事本复制和粘贴到 cmd 时遇到了这个问题。

回答by Enamul Hassan

When the same code works on one PC, but it shows the error in another, the best solution I have ever found is compiling like the following:

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

javac HelloWorld.java
java -cp . HelloWorld