天天看點

“找不到或加載主類”是什麼意思?

本文翻譯自:What does “Could not find or load main class” mean?

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?

這是什麼意思,是什麼原因造成的,以及應該如何解決?

#1樓

參考:https://stackoom.com/question/1Dv3Y/找不到或加載主類-是什麼意思

#2樓

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

(或

javaw

)指令啟動程式的正确方法。

The normal syntax 1 is this:

正常文法1是這樣的:
java [ <option> ... ] <class-name> [<argument> ...]
           

where

<option>

is a command line option (starting with a "-" character),

<class-name>

is a fully qualified Java class name, and

<argument>

is an arbitrary command line argument that gets passed to your application.

其中

<option>

是指令行選項(以“-”字元開頭),

<class-name>

是标準Java類名稱,而

<argument>

是傳遞給應用程式的任意指令行參數。

1 - There is a second syntax for "executable" JAR files which I will describe at the bottom.

1-我将在底部描述“可執行” JAR檔案的第二種文法。

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

按照慣例,該類的全限定名(FQN)就像在Java源代碼中一樣;

eg

例如
packagename.packagename2.packagename3.ClassName
           

However some versions of the

java

command allow you to use slashes instead of periods;

但是,某些版本的

java

指令允許您使用斜杠代替句點。

eg

例如
packagename/packagename2/packagename3/ClassName
           

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

指令應如下所示的示例:
java -Xmx100m com.acme.example.ListUsers fred joe bert
           

The above is going to cause the

java

command to do the following:

以上将導緻

java

指令執行以下操作:
  1. Search for the compiled version of the

    com.acme.example.ListUsers

    class. 搜尋

    com.acme.example.ListUsers

    類的編譯版本。
  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[])

    . 檢查該類是否具有

    main

    方法,該方法具有

    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[]

    . 調用該方法,以

    String[]

    将指令行參數(“ fred”,“ joe”,“ bert”)傳遞給它。

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

java

command was not able to find the class.

java

指令無法找到該類。

And indeed, the "..." in the message will be the fully qualified class name that

java

is looking for.

實際上,消息中的“ ...”将是

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

(或者...正确的類名,但格式錯誤。)考慮以上示例,這裡有多種錯誤的方法來指定類名:
  • Example #1 - a simple class name: Example#1-一個簡單的類名: 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; 當在

    com.acme.example

    之類的包中聲明該類時,則必須在

    java

    指令中使用完整的類名, 包括包名;
    eg 例如
  • Example #2 - a filename or pathname rather than a class name: Example#2-檔案名或路徑名而不是類名:
  • Example #3 - a class name with the casing incorrect: Example#3-類名的大小寫不正确:
  • Example #4 - a typo Example#4-錯字
  • Example #5 - a source filename Example#5-源檔案名
  • Example #6 - you forgot the class name entirely Example#6-您完全忘記了類名

Reason #2 - the application's classpath is incorrectly specified 原因#2-應用程式的類路徑指定不正确

The second likely cause is that the class name is correct, but that the

java

command cannot find the class.

第二個可能的原因是類名正确,但是

java

指令找不到該類。

To understand this, you need to understand the concept of the "classpath".

要了解這一點,您需要了解“類路徑”的概念。

This is explained well by the Oracle documentation:

Oracle文檔對此作了很好的解釋:
  • The

    java

    command documentation

    java

    指令文檔
  • Setting the Classpath . 設定類路徑 。
  • The Java Tutorial - PATH and CLASSPATH Java教程-PATH和CLASSPATH

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 understands at least the basics of how the Java classpath mechanisms works.) (是的,請閱讀它們。Java程式員至少了解 Java類路徑機制的基本原理很重要。)
  2. Look at command line and / or the CLASSPATH environment variable that is in effect when you run the

    java

    command. 檢視指令行和/或運作

    java

    指令時有效的CLASSPATH環境變量。
    Check that the directory names and JAR file names are correct. 檢查目錄名和JAR檔案名是否正确。
  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. 如果類路徑中有相對路徑名,請從運作

    java

    指令時有效的目前目錄中檢查它們是否正确解析...。
  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. 請注意,Windows與Linux和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.) (類路徑分隔符

    ;

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

通過将完全限定的名稱映射到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. 如果您的目錄結構與上述模式的包命名不比對,則JVM将找不到您的類。
  • If you attempt rename a class by moving it, that will fail as well ... but the exception stacktrace will be different. 如果您嘗試通過移動某個類來重命名該類,則該操作也會失敗...但是異常stacktrace會有所不同。 It is liable to say something like this: 可能會這樣說: because the FQN in the class file doesn't match what the class loader is expecting to find. 因為類檔案中的FQN與類加載器期望找到的内容不比對。

To give a concrete example, supposing that:

舉一個具體的例子,假設:
  • you want to run

    com.acme.example.Foon

    class, 您想運作

    com.acme.example.Foon

    類,
  • the full file path is

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

    , 完整的檔案路徑是

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

  • your current working directory is

    /usr/local/acme/classes/com/acme/example/

    , 您目前的工作目錄是

    /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

    -classpath

    option can be shortened to

    -cp

    in most Java releases. 在大多數Java版本中,可以将

    -classpath

    選項縮短為

    -cp

    Check the respective manual entries for

    java

    ,

    javac

    and so on. 檢查

    java

    javac

    等相應的手冊條目。
  • Think carefully when choosing between absolute and relative pathnames in classpaths. 在類路徑中的絕對路徑名和相對路徑名之間進行選擇時,請仔細考慮。 Remember that a relative pathname may "break" if the current directory changes. 請記住,如果目前目錄更改,則相對路徑名可能會“中斷”。

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需要查找:
  • the class itself. 類本身。
  • all classes and interfaces in the superclass hierarchy (eg see Java class is present in classpath but startup fails with Error: Could not find or load main class ) 超類層次結構中的所有類和接口(例如,看到Java類存在于類路徑中,但啟動失敗并顯示錯誤:找不到或加載主類 )
  • all classes and interfaces that are referred to by means of variable or variable declarations, or method call or field access expressions. 通過變量或變量聲明,方法調用或字段通路表達式引用的所有類和接口。

(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

package

declaration.

有時會發生某人将源代碼檔案放入其源代碼樹中錯誤的檔案夾中的情況,或者他們忽略了

package

聲明。

If you do this in an IDE, the IDE's compiler will tell you about this immediately.

如果您在IDE中執行此操作,則IDE的編譯器會立即告訴您有關此資訊。

Similarly if you use a decent Java build tool, the tool will run

javac

in a way that will detect the problem.

同樣,如果您使用不錯的Java建構工具,該工具将以檢測問題的方式運作

javac

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.

但是,如果您手工建構Java代碼,則可以通過這種方式進行處理,以使編譯器不會注意到問題,并且生成的“ .class”檔案不在您期望的位置。

Still can't find the problem? 還是找不到問題?

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

).

嘗試将

-Xdiag

選項添加到

java

指令行(作為

java

之後的第一件事)。

It will output various things about class loading, and this may offer you clues as to what the real problem is.

它将輸出有關類加載的各種資訊,這可能會為您提供真正問題所在的線索。

Also, consider possible problems caused by copying and pasting invisible or non-ASCII characters from websites, documents and so on.

另外,請考慮由網站,文檔等複制和粘貼不可見或非ASCII字元引起的可能問題。

And consider "homoglyphs", were two letters or symbols look the same ... but aren't.

考慮“象形文字”,如果兩個字母或符号看起來相同……卻不相同。

The

java -jar <jar file>

syntax

java -jar <jar file>

文法

The alternative syntax used for "executable" JAR files is as follows:

用于“可執行” JAR檔案的替代文法如下:
java [ <option> ... ] -jar <jar-file-name> [<argument> ...]
           

eg

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

In this case the name of the entry-point class (ie

com.acme.example.ListUser

) and the classpath are specified in the MANIFEST of the JAR file.

在這種情況下,入口點類的名稱(即

com.acme.example.ListUser

)和類路徑在JAR檔案的清單中指定。

IDEs 內建開發環境

A typical Java IDE has support for running Java applications in the IDE JVM itself or in a child JVM.

典型的Java IDE支援在IDE JVM本身或子JVM中運作Java應用程式。

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使用其自身的機制來構造運作時類路徑,辨別主類并建立

java

指令行。

However it is still possible for this exception to occur, if you do things behind the back of the IDE.

但是,如果您在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.

例如,如果您先前已在Eclipse中為Java應用程式設定了Application Launcher,然後在不通知Eclipse的情況下将包含“ main”類的JAR檔案移動到了檔案系統中的其他位置,則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可能也很容易混淆。

IDE's are hugely complicated pieces of software comprising many interacting parts.

IDE是非常複雜的軟體,包含許多互動部分。

Many of these parts adopt various caching strategies in order to make the IDE as a whole responsive.

這些部分中的許多部分都采用了各種緩存政策,以使IDE整體具有響應能力。

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 things lie restarting your IDE and rebuilding the project.

如果您懷疑這可能發生,那麼值得嘗試的事情就是重新啟動IDE并重建項目。

Other References 其他參考

  • From the Oracle Java Tutorials - Common Problems (and Their Solutions) 來自Oracle Java教程- 常見問題(及其解決方案)

#3樓

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.

我隻是删除了該引用,将其再次添加,然後再次正常工作。

#4樓

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.

在存儲的驅動器中鍵入“ cd(檔案夾名稱)”并進行編譯。

For Example, if my program stored on the D drive, type "D:" press enter and type " cd (folder name)".

例如,如果我的程式存儲在D驅動器上,則鍵入“ D:”,然後按Enter鍵并鍵入“ cd(檔案夾名稱)”。

#5樓

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方法的類名提供給解釋器。

#6樓

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