“Could not find or load main class"是什么意思?意思? [英] What does "Could not find or load main class" mean?

查看:22
本文介绍了“Could not find or load main class"是什么意思?意思?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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 ...

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

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

推荐答案

java 命令语法

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

The java <class-name> command syntax

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

正常的语法1是这样的:

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

其中 是命令行选项(以-"字符开头), 是完全限定的 Java类名, 是传递给应用程序的任意命令行参数.

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.

1 - 在这个答案的结尾处描述了其他一些语法.

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

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

    packagename.packagename2.packagename3.ClassName

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

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

    packagename/packagename2/packagename3/ClassName

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

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

以下是 java 命令的示例:

Here is an example of what a java command should look like:

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

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

The above is going to cause the java command to do the following:

  1. 搜索 com.acme.example.ListUsers 类的编译版本.
  2. 加载类.
  3. 检查该类是否具有 main 方法,其中 signature返回类型modifierspublic static void main(String[]).(注意,方法参数的名称不是签名的一部分.)
  4. 调用该方法,将命令行参数(fred"、joe"、bert")作为 String[] 传递给它.
  1. Search for the compiled version of the com.acme.example.ListUsers class.
  2. Load the class.
  3. Check that the class has a main method with signature, return type and modifiers given by public static void main(String[]). (Note, the method argument's name is NOT part of the signature.)
  4. Call that method passing it the command line arguments ("fred", "joe", "bert") as a String[].

Java 找不到类的原因

当您收到消息无法找到或加载主类..."时,这意味着第一步失败.java 命令无法找到该类.事实上,……"消息中将是 java 正在寻找的 完全限定类名.

Reasons why Java cannot find the class

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

那为什么会找不到类呢?

So why might it be unable to find the class?

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

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 ways to specify the class name:

  • 示例 #1 - 一个简单的类名:

  • Example #1 - a simple class name:

java ListUser

com.acme.example等包中声明类时,必须使用完整的类名包括java中的包名 命令;例如

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

java com.acme.example.ListUser

  • 示例 2 - 文件名或路径名而不是类名:

  • Example #2 - a filename or pathname rather than a class name:

    java ListUser.class
    java com/acme/example/ListUser.class
    

  • 示例 3 - 大小写不正确的类名:

  • Example #3 - a class name with the casing incorrect:

    java com.acme.example.listuser
    

  • 示例 4 - 错别字

  • Example #4 - a typo

    java com.acme.example.mistuser
    

  • 示例 #5 - 源文件名(Java 11 或更高版本除外;见下文)

  • Example #5 - a source filename (except for Java 11 or later; see below)

    java ListUser.java
    

  • 示例 #6 - 你完全忘记了类名

  • Example #6 - you forgot the class name entirely

    java lots of arguments
    

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

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

    • The java command documentation
    • Setting the Classpath.
    • The Java Tutorial - PATH and CLASSPATH

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

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

    1. 阅读上面链接的三个文件.(是的……阅读它们!Java 程序员必须理解至少 Java 类路径机制如何工作的基础知识.)
    2. 查看运行 java 命令时生效的命令行和/或 CLASSPATH 环境变量.检查目录名和 JAR 文件名是否正确.
    3. 如果类路径中有相对路径名,请检查它们是否正确解析......从当前目录中,当您运行java命令时生效.
    4. 检查该类(错误消息中提到的)是否可以位于有效类路径中.
    5. 请注意,Windows 与 Linux 和 Mac OS 的类路径语法不同.(类路径分隔符在 Windows 上是 ; ,在其他上是 : .如果你为你的平台使用了错误的分隔符,你不会得到明确的错误消息.相反,您将在路径上得到一个不存在的文件或目录,该文件或目录将被静默忽略.)
    1. Read the three documents linked above. (Yes ... READ them! It is important that a Java programmer understands at 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 java command. Check that the directory names and JAR file names are correct.
    3. If there are relative pathnames in the classpath, check that they resolve correctly ... from the current directory that is in effect when you run the java command.
    4. Check that the class (mentioned in the error message) can be located on the effective classpath.
    5. Note that the classpath syntax is different for 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.)

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

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

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

    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/com/acme/example/Foon.class
    

    如果你把/usr/local/acme/classes/com/acme/example"在类路径上,则 JVM 将无法找到该类.

    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.

    如果您的类 FQN 是 com.acme.example.Foon,那么 JVM 将查找Foon.class";在目录com/acme/example"中:

    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":

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

    • 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 rename a 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>)
    

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

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

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

    To give a concrete example, supposing that:

    • 你想运行 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.检查 javajavac 等的相应手册条目.
    • 在类路径中选择绝对路径名和相对路径名时要仔细考虑.请记住,相对路径名可能会中断".如果当前目录发生变化.
    • The -classpath option can be shortened to -cp in most Java releases. Check the respective manual entries for java, javac and 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.

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

    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:

    (注意:JLS 和 JVM 规范允许 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.)

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

    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 package declaration. 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 javac in 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.

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

    There lots of things to check, and it is easy to miss something. Try adding the -Xdiag option to the java command 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.

    另外,请考虑从网站、文档等中复制和粘贴不可见或非 ASCII 字符可能导致的问题.并考虑同形文字",其中两个字母或符号看起来相同……但实际上并非如此.

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

    最后,如果您尝试从 (META-INF/*.SF) 中签名不正确的 JAR 文件启动,或者如果在MANIFEST.MF 文件(参见 https://stackoverflow.com/a/67145190/139985).

    Finally, you can apparently run into this problem if you try to launch from a JAR file with incorrect signatures in (META-INF/*.SF) or if there is a syntax error in the MANIFEST.MF file (see https://stackoverflow.com/a/67145190/139985).

    使用 java 命令 启动 Java 程序有三种替代语法.

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

    1. 用于启动可执行文件"的语法JAR文件如下:

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

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

    例如

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

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

    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.

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

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

    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>.

    从 Java 11 开始,您可以使用 java 命令使用以下语法编译和运行单个源代码文件:

    From Java 11 onwards, you can use the java command to compile and run a single source code file using the following syntax:

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

    其中 是(通常)后缀为.java"的文件.

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

    更多详细信息,请参考您使用的 Java 版本的 java 命令的官方文档.

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

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

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

    但是,如果您在 IDE 背后进行操作,仍然有可能发生此异常.例如,如果您之前在 Eclipse 中为您的 Java 应用程序设置了一个应用程序启动器,然后您移动了包含主"文件的 JAR 文件.类到文件系统中的不同位置不告诉 Eclipse,Eclipse 会不知不觉地启动带有错误类路径的 JVM.

    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 中遇到此问题,请检查是否有过时的 IDE 状态、损坏的项目引用或损坏的启动器配置.

    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 是由许多交互部分组成的极其复杂的软件.其中许多部分采用了各种缓存策略,以使 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.

    这篇关于“Could not find or load main class"是什么意思?意思?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆