1688

新しい Java 開発者が経験する一般的な問題は、プログラムの実行に失敗して次のエラー メッセージが表示されることです。 Could not find or load main class ...

これは何を意味し、何が原因で、どのように修正する必要がありますか?

4

59 に答える 59

1510

java <class-name>コマンド構文

まず、java(またはjavaw) コマンドを使用してプログラムを起動する正しい方法を理解する必要があります。

通常の構文1は次のとおりです。

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

ここ<option>で、 はコマンド ライン オプション (「-」文字で始まる) で<class-name>あり、完全修飾 Java クラス名であり<arg>、アプリケーションに渡される任意のコマンド ライン引数です。


1 - この回答の終わり近くで説明されている他の構文がいくつかあります。

クラスの完全修飾名 (FQN) は、Java ソース コードの場合と同様に慣例的に記述されます。例えば

    packagename.packagename2.packagename3.ClassName

ただし、javaコマンドの一部のバージョンでは、ピリオドの代わりにスラッシュを使用できます。例えば

    packagename/packagename2/packagename3/ClassName

これは (紛らわしいことに) ファイルのパス名のように見えますが、そうではありません。完全修飾名という用語は、標準的な Java 用語であることに注意してください...混乱させるために私が作ったものではありません :-)

コマンドの例を次に示しjavaます。

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

上記により、javaコマンドは次のことを実行します。

  1. com.acme.example.ListUsersクラスのコンパイル済みバージョンを検索します。
  2. クラスをロードします。
  3. によって指定された署名戻り値の型、および修飾子mainを持つメソッドがクラスにあることを確認してください。(メソッド引数の名前は署名の一部ではないことに注意してください。)public static void main(String[])
  4. そのメソッドを呼び出して、コマンド ライン引数 ("fred"、"joe"、"bert") をString[].

Java がクラスを見つけられない理由

「Could not find or load main class ...」というメッセージが表示された場合は、最初のステップが失敗したことを意味します。javaコマンドはクラスを見つけることができませんでした。実際、メッセージ内の「...」は、探している完全修飾クラス名になります。java

では、なぜクラスを見つけることができないのでしょうか?

理由 #1 - classname 引数を間違えた

最初に考えられる原因は、間違ったクラス名を指定した可能性があることです。(または ... 正しいクラス名ですが、形式が間違っています。) 上記の例を考慮して、クラス名を指定するさまざまな間違った方法を次に示します。

  • 例 #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
    

理由 2 - アプリケーションのクラスパスが正しく指定されていない

2 番目に考えられる原因は、クラス名は正しいが、javaコマンドがクラスを見つけられないことです。これを理解するには、「クラスパス」の概念を理解する必要があります。これは、Oracleのドキュメントでよく説明されています。

そのため...クラス名を正しく指定した場合、次に確認することは、クラスパスを正しく指定したことです。

  1. 上にリンクされている 3 つの文書を読んでください。(はい... 読んでください! Java プログラマーは、少なくとも Java クラスパスメカニズムの仕組みの基本を理解していることが重要です。)
  2. コマンドラインおよび / またはコマンドの実行時に有効な CLASSPATH 環境変数を調べますjava。ディレクトリ名とJARファイル名が正しいことを確認してください。
  3. クラスパスに相対パス名がある場合は、コマンドを実行したときに有効な現在のディレクトリから、それらが正しく解決されることを確認してくださいjava
  4. クラス (エラー メッセージに示されている) が有効なクラスパス上にあることを確認してください。
  5. Windows と Linux および Mac OS では、クラスパスの構文が異なることに注意してください。(クラスパスセパレーターは;Windows と:その他のものにあります。プラットフォームに間違ったセパレーターを使用しても、明示的なエラーメッセージは表示されません。代わりに、パス上に存在しないファイルまたはディレクトリが表示され、黙って無視されます。 .)

理由 #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 はクラスを見つけられません。

  • クラスを移動して名前を変更しようとすると、それも失敗します...ただし、例外スタックトレースは異なります。次のようなことを言いがちです。

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

    クラス ファイル内の FQN が、クラス ローダーが期待しているものと一致しないためです。

具体例を挙げると、次のようになります。

  • 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
  • クラスパスで絶対パス名と相対パス名のどちらを選択するかは慎重に検討してください。現在のディレクトリが変更されると、相対パス名が「壊れる」可能性があることに注意してください。

理由 2c - クラスパスに依存関係がない

クラスパスには、アプリケーションが依存する他の(システム以外の) クラスをすべて含める必要があります。(システム クラスは自動的に配置されるため、これについて気にする必要はほとんどありません。) メイン クラスを正しくロードするには、JVM が以下を見つける必要があります。

(注: JLS および JVM の仕様では、JVM がクラスを「遅延」してロードする範囲が許可されており、これはクラスローダー例外がスローされたときに影響を与える可能性があります。)

理由 3 - クラスが間違ったパッケージで宣言されている

packageソース コード ツリー内の間違ったフォルダーにソース コード ファイルを配置したり、宣言を省略したりすることがあります。IDE でこれを行うと、IDE のコンパイラがこれについてすぐに通知します。同様に、適切な Java ビルド ツールを使用すると、ツールはjavac問題を検出する方法で実行されます。ただし、Java コードを手動でビルドすると、コンパイラが問題に気付かず、結果の ".class" ファイルが期待どおりの場所にないような方法でビルドできます。

それでも問題が見つかりませんか?

確認する項目が多く、見落としがちです。-Xdiagオプションをjavaコマンド ラインに追加してみてください( の後の最初のものとしてjava)。クラスのロードに関するさまざまな情報が出力されます。これにより、実際の問題が何であるかについての手がかりが得られる場合があります。

また、Web サイトやドキュメントなどから非表示または非 ASCII 文字をコピーして貼り付けることによって発生する可能性のある問題についても考慮してください。そして、2 つの文字または記号が同じように見えますが、そうではない「ホモグリフ」を考えてみましょう。

の署名が無効または正しくない場合、この問題が発生する可能性がありますMETA-INF/*.SF。お気に入りの ZIP エディターで .jar を開き、.jar ファイルがMETA-INFなくなるまでファイルを削除してみてくださいMANIFEST.MF。ただし、これは一般的に推奨されません。(無効な署名は、元の署名付き JAR ファイルに誰かがマルウェアを挿入した結果である可能性があります。無効な署名を消去すると、アプリケーションがマルウェアに感染することになります!)署名を作成するか、(本物の) 元のソース コードから再構築します。

MANIFEST.MF最後に、ファイルに構文エラーがあると、この問題が発生する可能性があります ( https://stackoverflow.com/a/67145190/139985を参照)。


の代替構文java

を使用して Java プログラムを起動するための代替構文が 3 つありますjava command

  1. 「実行可能」JAR ファイルの起動に使用される構文は次のとおりです。

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

    例えば

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

    エントリポイント クラスの名前 (つまりcom.acme.example.ListUser) とクラスパスは、JAR ファイルの MANIFEST で指定されます。

  2. モジュール (Java 9 以降) からアプリケーションを起動するための構文は次のとおりです。

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

    エントリポイント クラスの名前は、<module>それ自体によって定義されるか、オプションの によって指定されます<mainclass>

  3. Java 11 以降では、javaコマンドを使用して、次の構文を使用して単一のソース コード ファイルをコンパイルおよび実行できます。

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

    <sourcefile>(通常) は、接尾辞「.java」が付いたファイルです。

詳細については、java使用している Java リリースのコマンドの公式ドキュメントを参照してください。


IDE

標準的な Java IDE は、IDE JVM 自体または子 JVM での Java アプリケーションの実行をサポートしています。IDE は独自のメカニズムを使用してランタイム クラスパスを構築し、メイン クラスを識別し、コマンド ラインを作成するため、これらは通常、この特定の例外の影響を受けません。java

ただし、IDE の背後で何かを行うと、この例外が発生する可能性があります。たとえば、以前に Eclipse で Java アプリ用の Application Launcher をセットアップしており、「メイン」クラスを含む JAR ファイルをEclipse に通知せずにファイル システム内の別の場所に移動した場合、Eclipse は無意識のうちに JVM を起動します。クラスパスが正しくありません。

つまり、IDE でこの問題が発生した場合は、古い IDE 状態、壊れたプロジェクト参照、壊れたランチャー構成などを確認してください。

IDE が単純に混乱する可能性もあります。IDE は、相互に作用する多くのパーツからなる非常に複雑なソフトウェアです。これらのパーツの多くは、IDE を全体として応答性の高いものにするために、さまざまなキャッシュ戦略を採用しています。これらは時々うまくいかないことがあり、考えられる症状の 1 つは、アプリケーションの起動時の問題です。これが起こっている可能性があると思われる場合は、IDE の再起動、プロジェクトの再構築など、他のことを試す価値があります。


その他の参考文献

于 2013-08-07T03:02:46.263 に答える
276

ソース コード名が HelloWorld.java の場合、コンパイルされたコードはHelloWorld.class.

次を使用して呼び出すと、そのエラーが発生します。

java HelloWorld.class

代わりに、これを使用します。

java HelloWorld
于 2014-05-21T11:06:35.633 に答える
165

クラスがパッケージに含まれている場合cdは、プロジェクトのルート ディレクトリに移動し、クラスの完全修飾名 (packageName.MainClassName) を使用して実行する必要があります。

例:

私のクラスはここにあります:

D:\project\com\cse\

私のメインクラスの完全修飾名は次のとおりです。

com.cse.Main

そこでcd、ルート プロジェクト ディレクトリに戻ります。

D:\project

次に、次のjavaコマンドを発行します。

java com.cse.Main

この回答は、初心者の Java プログラマーをよくある間違いによって引き起こされるフラストレーションから救うためのものです。Javaクラスパスに関するより深い知識については、受け入れられた回答を読むことをお勧めします。

于 2015-03-06T03:20:27.140 に答える
40

コマンドラインでクラスパスを指定すると役に立ちました。例えば:

  1. 新しいフォルダを作成し、C:\temp

  2. C:\temp次のクラスを含むファイル Temp.java を に作成します。

     public class Temp {
         public static void main(String args[]) {
             System.out.println(args[0]);
         }
     }
    
  3. folderC:\tempでコマンド ラインを開き、次のコマンドを記述して Temp クラスをコンパイルします。

     javac Temp.java
    
  4. コンパイルされた Java クラスを実行し、-classpathJRE にクラスの場所を知らせるオプションを追加します。

     java -classpath C:\temp Temp Hello!
    
于 2014-07-02T11:11:45.070 に答える
21

-Xdiagを試してください。

Steve C の回答は考えられるケースを適切にカバーしていますが、クラスが見つからないかロードされていないかどうかを判断するのはそれほど簡単ではない場合があります。使用しますjava -Xdiag(JDK 7 以降)。これは、メッセージ メッセージが何を意味するかについてのヒントを提供する素敵なスタック トレースを出力しますCould not find or load main class

たとえば、メイン クラスで使用されている他のクラスが見つからず、メイン クラスのロードを妨げていることを示すことができます。

于 2016-08-24T08:13:26.843 に答える
21

この場合、次のようなエラーが発生しました。

java -cp lib.jar com.mypackage.Main

;Windows および:Unix で動作します。

java -cp lib.jar; com.mypackage.Main
于 2016-09-22T07:35:26.363 に答える
16

問題の原因がメインクラスとは関係ない場合があり、これを見つけるのは難しい方法でした。私が移動したのは参照ライブラリであり、次のことがわかりました。

メイン クラス xxx Linux が見つからないか、読み込めませんでした

その参照を削除して再度追加したところ、再び正常に機能しました。

于 2013-11-01T18:04:56.943 に答える
12

私は同じ問題を抱えていて、最終的に間違いを見つけました:)コンパイルにこのコマンドを使用したところ、正しく機能しました:

javac -cp "/home/omidmohebbi/AAAATest/jars/core-1.7.jar:/home/omidmohebbi/AAAATest/jars/javase-1.7.jar:/home/omidmohebbi/AAAATest/jars/qrgen-1.2.jar" qrcode.java

しかし、このコマンドはうまくいきませんでした (メイン クラスを見つけたりロードしたりできませんでしたqrcode):

java -cp "/home/omidmohebbi/AAAATest/jars/core-1.7.jar:/home/omidmohebbi/AAAATest/jars/javase-1.7.jar:/home/omidmohebbi/AAAATest/jars/qrgen-1.2.jar" qrcode

最後に、クラスパスの最後に「:」文字を追加したところ、問題は解決しました。

java -cp "/home/omidmohebbi/AAAATest/jars/core-1.7.jar:/home/omidmohebbi/AAAATest/jars/javase-1.7.jar:/home/omidmohebbi/AAAATest/jars/qrgen-1.2.jar:" qrcode
于 2019-03-18T06:19:24.340 に答える
9

私の場合、クラス名ではなくソースファイル名を指定したため、エラーが発生しました。

main メソッドを含むクラス名をインタープリターに提供する必要があります。

于 2014-03-12T00:37:57.023 に答える
8

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>
于 2017-06-15T16:19:08.490 に答える
7

ここでのすべての回答は、Windows ユーザーに向けられているようです。Mac の場合、クラスパス セパレータは:であり、 ではありません;。を使用してクラスパスを設定するエラー;がスローされないため、Windows から Mac に移行する場合、これを発見するのが難しい場合があります。

対応する Mac コマンドは次のとおりです。

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

この例では、パッケージはどこにcom.testあり、libフォルダーもクラスパスに含まれます。

于 2016-10-04T16:08:04.307 に答える
6

どういうわけかクラスパスを間違って設定していると思いましたが、問題は次のように入力したことです。

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

それ以外の:

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

完全修飾の意味は、完全なパッケージ名の代わりに完全なパス名を含めることを意味すると思いました。

于 2015-09-02T05:58:27.343 に答える
5

私の場合の問題を修正したのは次のとおりです。

実行するプロジェクト/クラスを右クリックし、Run AsRun Configurations。次に、既存の構成を修正するか、次の方法で新しい構成を追加する必要があります。

[クラスパス] タブを開き、 [詳細... ] ボタンをクリックして、プロジェクトのbinフォルダーを追加します。

于 2016-01-16T10:26:31.050 に答える
5

Windows では.;、先頭に CLASSPATH 値を置きます。

。(ドット) は「現在のディレクトリを調べる」という意味です。これは恒久的な解決策です。

また、 set で「1回」設定することもできますCLASSPATH=%CLASSPATH%;.。これは、コマンド ウィンドウが開いている限り続きます。

于 2015-10-24T21:18:17.800 に答える
4

public static void mainJava では、Java インタープリター実行可能ファイルを使用してコマンド ラインから JVM を実行し、 (PSVM)を使用してクラス ファイルからプログラムを起動しようとすると、JVM へのクラスパス パラメーターが正確で、クラスファイルがクラスパスに存在します:

エラー: メイン クラスが見つからないか、ロードされていません

これは、PSVM を含むクラス ファイルをロードできなかった場合に発生します。考えられる理由の 1 つは、クラスがインターフェイスを実装しているか、クラスパスにない別のクラスを拡張している可能性があることです。通常、クラスがクラスパスにない場合、スローされるエラーはそのことを示します。ただし、使用中のクラスが拡張または実装されている場合、Java はクラス自体をロードできません。

参考:https ://www.computingnotes.net/java/error-main-class-not-found-or-loaded/

于 2015-09-18T03:01:01.750 に答える
3

Java MongoDB JDBC 接続のテスト中にも、同様のエラーに直面しました。最終的な解決策を手短に要約するのは良いことだと思います。そうすれば、将来、誰でも 2 つのコマンドを直接調べて、さらに先に進むことができます。

Java ファイルと外部依存関係 (JAR ファイル) が存在するディレクトリーにいるとします。

コンパイル:

javac -cp mongo-java-driver-3.4.1.jar JavaMongoDBConnection.java
  • -cp - クラスパス引数; 依存するすべての JAR ファイルを 1 つずつ渡します
  • *.java - これは main メソッドを持つ Java クラス ファイルです。SDSD

走る:

java -cp mongo-java-driver-3.4.1.jar: JavaMongoDBConnection
  • すべての依存関係 JAR ファイルが終了した後、コロン (Unix) / コンマ (Windows) を確認してください。
  • 最後に、拡張子なし (.class または .java なし) のメイン クラス名を確認します。
于 2018-01-26T20:15:13.550 に答える
2

実行後にこのエラーが発生しましたmvn eclipse:eclipse.classpathこれは私のファイルを少し台無しにしました。

.classpathからの行を変更する必要がありました

<classpathentry kind="src" path="src/main/java" including="**/*.java"/>
<classpathentry kind="src" path="src/main/resources" excluding="**/*.java"/>

<classpathentry kind="src" path="src/main/java" output="target/classes" />
<classpathentry kind="src" path="src/main/resources" excluding="**"  output="target/classes" />
于 2015-12-14T14:14:27.273 に答える
2

少し時間がかかった別の問題があります。コマンド ラインのクラス パス パラメータが期待どおりに動作しません。私は MacOS で CLI を直接呼び出しており、呼び出しに 2 つの jar を含めています。

たとえば、これらは両方とも、メイン クラスの名前についてツールを混乱させていました。

これは、アスタリスクが原因で引数が正しく解析されなかったためです。

java -cp path/to/jars/* com.mypackage.Main

そして、これは - 理由がわかりません:

java -cp "*.jar" com.mypackage.Main

これはうまくいきました:

java -cp "path/to/jars/*" com.mypackage.Main

2 つの jar を明示的にリストすることも機能しました。

java -cp path/to/jars/jar1.jar:path/to/jars/jar2.jar com.mypackage.Main

于 2019-11-26T20:08:03.150 に答える
2

ときどき、あなたが試したことがあるかもしれないいくつかのオンライン コンパイラでは、記述せずpublic class [Classname]class [Classname].

于 2017-08-18T18:29:30.190 に答える
0
  • IntelliJ IDEAで、グローバルライブラリ* とローカル ライブラリを確認します
  • ライブラリのバージョン ファイルpom.xmlをチェックインします。古いライブラリである可能性があります。
  • それらは、以前の回答で言及された非常に多くの可能性であり、それらも試す必要があります
于 2020-12-28T17:12:18.697 に答える
0

IntelliJ で作成したデモ プログラムでこの問題が発生しました。

それを解決するには、次の 2 つのポイントがあります。

  1. プログラムのパッケージ名
  2. ターミナル/コマンド プロンプトの現在の作業ディレクトリ

私のデモプログラム:

package io.rlx.tij.c2;

public class Ex10 {
    public static void main(String[] args) {
        // do something
    }
}

ソースコードのパス:

../projectRoot/src/main/java/io/rlx/tij/c2/Ex10.java
  1. java次のディレクトリに移動します。cd ../projectRoot/src/main/java
  2. クラスにコンパイルします。javac ./io/rlx/tij/c2/Ex10.java
  3. プログラムを実行します。java io.rlx.tij.c2.Ex10

でプログラムを../projectRoot/src/main/java/io/rlx/tij/c2実行するか、パッケージ名なしで実行すると、次のエラーが発生します: Error: Could not find or load main class.

于 2020-05-10T11:48:21.197 に答える