Could not find or load main class"とはどういう意味ですか?

Javaを初めて開発する人がよく経験する問題に、「プログラムが実行できない」というエラーメッセージがあります。 Could not find or load main class ...` というエラーメッセージが表示され、プログラムが実行できない。

これは何を意味し、何が原因で、どのように修正すればよいのでしょうか。

質問へのコメント (1)
ソリューション

java ` コマンドの構文

まず最初に、java (または javaw) コマンドを使用してプログラムを起動する正しい方法を理解する必要があります。 通常の構文1はこのようなものです。

    java [  ... ]  [ ...]

ここで、はコマンドラインオプション("-"で始まる文字)、は完全修飾Javaクラス名、``はアプリケーションに渡される任意のコマンドラインの引数である。
1 - JARファイルには、2つ目の構文があります。 クラスの完全修飾名 (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 クラスを検索します。
    1. クラスをロードする。
    1. クラスが public static void main(String[]) で与えられる シグネチャーリターンタイプモディファイア を持つ main メソッドを持つことを確認する。 (注意: メソッドの引数名はシグネチャの NOT 部分です。)
  2. コマンドライン引数("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 ListUser.java

  • 例6 - クラス名を完全に忘れている。 java 引数が多い 原因2:アプリケーションのクラスパスが正しく指定されていない。

    次に考えられるのは、クラス名は正しいが java コマンドがそのクラスを見つけられない場合です。 これを理解するには、"classpath" の概念を理解する必要があります。 これは、Oracleのドキュメントで よく 説明されています。

  • The java command documentation]1.

  • クラスパスの設定]2

  • Javaチュートリアル - PATHとCLASSPATH。 そこで......クラス名を正しく指定できたなら、次に確認すべきは、クラスパスを正しく指定できたかどうかです。 1.上記のリンク先の3つのドキュメントを読んでください。 (そうです ...読んでください。 Javaプログラマーは、少なくともJavaのクラスパスの仕組みの基本を理解することが重要です)。 1.コマンドラインと/またはjavaコマンドを実行したときに有効になっているCLASSPATH環境変数を見てください。 ディレクトリ名とJARファイル名が正しいことを確認します。 1.クラスパスに相対パス名がある場合、それらが正しく解決されることを確認します ... java コマンドを実行したときに有効なカレントディレクトリから。 1.1. (エラーメッセージにある) クラスが 有効な クラスパスに存在するかどうか確認してください。 1.クラスパスのシンタックスは、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はクラスを見つけることができません'。
  • もし、クラスを移動して*名前を変えようとすると、同様に失敗します...しかし、例外スタックトレースは異なるでしょう。 しかし、例外のスタックトレースは異なります。 原因: java.lang.NoClassDefFoundError: <path> (間違った名前: ) これは、クラスファイルの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` などのそれぞれのマニュアルを確認してください。

  • クラスパスで絶対パス名と相対パス名のどちらを選択するかは、慎重に考えてください。 相対パス名は、カレントディレクトリが変更された場合、 "break"する可能性があることを覚えておいてください。
    理由その2c - クラスパスから依存関係が抜けている

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

  • クラス自体

  • スーパークラス階層にあるすべてのクラスとインターフェイス (例: https://stackoverflow.com/questions/42880748 を参照)

  • 変数や変数宣言、メソッド呼び出しやフィールドアクセス式によって参照されるすべてのクラスとインターフェース。 (注意:JLS と JVM の仕様では、JVM がクラスを "lazily" ロードする範囲をある程度認めており、これはクラスローダー例外がスローされるときに影響します)。 理由その3 - クラスが間違ったパッケージで宣言されている。

    たまに、ソースコードのファイルを ソースコードツリー内の間違ったフォルダに入れたり、パッケージの宣言を省いたりします。 IDEでこのようなことをすると、IDEのコンパイラはすぐにこのことを教えてくれます。 同様に、まともなJavaのビルドツールを使っていれば、そのツールは問題を検出する方法で javac を実行します。 しかし、手作業でJavaのコードをビルドする場合、コンパイラが問題に気づかないような方法でビルドしてしまい、結果として ".class"ファイルが期待した場所にないことがありえます。 それでも問題が見つかりませんか?

    確認することがたくさんあり、見落としが起こりがちです。 javaコマンドラインに-Xdiagオプションを追加してみてください (java` の後の最初の文字として)。 クラスの読み込みに関する様々なことが出力され、何が本当の問題なのかを知る手がかりになるかもしれません。 また、Webサイトやドキュメントなどから、見えない文字や非ASCII文字をコピー&ペーストすることによって引き起こされる可能性のある問題も考慮してみてください。 また、2つの文字や記号が同じに見える......しかしそうではない、「ホモグリフ」についても考えてみてください。

    java -jar ` 構文

    実行可能なJARファイルに使用される代替構文は、以下のとおりです。

  java [  ... ] -jar  [ ...]

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

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

IDEs

典型的なJava IDEは、IDE JVM自体または子JVMでJavaアプリケーションを実行するためのサポートを持っています。 IDEはランタイムクラスパスを構築し、メインクラスを識別し、javaコマンドラインを作成するために独自のメカニズムを使用するので、これらはこの特定の例外から一般的に免除されています。 しかし、IDEの裏側でいろいろなことをすると、この例外が発生する可能性があるのです。 たとえば、Eclipse で Java アプリの Application Launcher を設定した後、"main" クラスを含む JAR ファイルをファイルシステム内の別の場所に移動した場合、Eclipse は意図せずに不正なクラスパスで JVM を起動することになります。 つまり、IDEでこの問題が発生した場合は、IDEの状態が古くなっていないか、プロジェクトの参照が壊れていないか、ランチャーの設定が壊れていないかなどを確認してください。 また、IDEが単に混乱している可能性もあります。 IDEは非常に複雑なソフトウェアであり、多くの相互作用する部分から構成されています。 これらのパーツの多くは、IDE が全体として応答するように、さまざまなキャッシュ戦略を採用しています。 これらは時々うまくいかないことがあり、考えられる症状の1つがアプリケーションの起動時の問題です。 もし、このような現象が起こっていると思われる場合は、IDE を再起動し、プロジェクトを再構築するなどの方法を試してみる価値があります。

その他の参考文献

解説 (11)

ソースコード名がHelloWorld.javaの場合、コンパイルされたコードは「HelloWorld.class」になります。

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

java HelloWorld.class

代わりに、これを使用してください。

java HelloWorld
解説 (8)

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

例:

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

D:\project\com\cse\

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

com.cse.Main

だから私はルートプロジェクトディレクトリに戻ります:

D:\project

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

java com.cse.Main

この答えは、一般的な間違いによって引き起こされた欲求不満から初心者Javaプログラマーを救うためのものです。Javaクラスパスに関するより深い知識を得るために、受け入れられた答えを読むことをお勧めします。

解説 (2)

メインクラスとメインメソッドを package で定義する場合は、クラスのフルネーム( packageName.MainClassName)を使用して、階層ディレクトリで実行する必要があります。

ソースコードファイル(Main.java)があると仮定します。

package com.test;

public class Main {

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

このコードを実行するには、ディレクトリ のようなパッケージにMain.Classを配置する必要があります。/com/test/Main.Java。 ルートディレクトリでは、 java com.test.Mainを使用します。

解説 (6)

同じコードが1つのPCで機能しているが、別のPCでエラーが表示されている場合、私が見つけた最良の解決策は、次のようにコンパイルすることです。

javac HelloWorld.java
java -cp . HelloWorld
解説 (5)

私を助けたのは、コマンドラインにクラスパスを指定することでした。例:

1。 新しいフォルダ C:\ tempを作成します。

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

    公開クラスの臨時{。
        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こんにちは。!
解説 (7)

エラーメッセージ(「メインクラスが見つからなかったか、読み込まれなかった」)によると、問題には2つのカテゴリがあります。

1。 メインクラスは見つかりませんでした。 2。 メインクラスをロードできませんでした(このケースは、受け入れられた回答では完全には説明されていません)。

完全に修飾されたクラス名に typoまたは間違った構文がある場合、または提供されたクラスパスに存在しない場合、メインクラスは見つかりません

クラスを開始できない場合メインクラスをロードできません。通常、メインクラスは別のクラスを拡張し、そのクラスは提供されたクラスパスに存在しません。

例:

public class YourMain extends org.apache.camel.spring.Main

ラクダ春が含まれていない場合、このエラーが報告されます。

解説 (11)

この場合、私はそのようなエラーを抱えていました。

java -cp lib.jar com.mypackage.Main

Windowsの場合は ;、Unixの場合は :で動作します。

java -cp lib.jar; com.mypackage.Main
解説 (2)

このコマンドを使用します。

java -cp . [PACKAGE.]CLASSNAME

例:クラス名がHello.javaから作成されたHello.classの場合は、次のコマンドを使用します。

java -cp . Hello

ファイルHello.javaがパッケージcom.demo内にある場合は、以下のコマンドを使用します。

java -cp . com.demo.Hello

JDK 8では、クラスファイルが同じフォルダーに存在することが何度も発生しますが、「java」コマンドはクラスパスを期待するため、 -cpを追加します。 .現在のフォルダをclasspathの参照として取得します。

解説 (8)

問題の原因となっているものがメインクラスとは関係ない場合もあり、私はこれを見つけるのに苦労しました。それは、私が移動させた参照されたライブラリで、それは私に与えました。

Could not find or load main class xxx Linux

その参照を削除して、もう一度追加したら、またうまくいきました。

解説 (5)

-Xdiag を試してください。

Steve Cの回答は考えられるケースをうまくカバーしていますが、クラスを見つけできないかロードできないかを判断するのはそれほど簡単ではない場合があります。 `` java -Xdiag```を使用します(JDK& nbsp; 7以降)。 これにより、「メインクラスが見つからないか、読み込めない」というメッセージの意味が示される素敵なスタックトレースが出力されます。

たとえば、メインクラスが使用していて見つからなかった他のクラスを指し、メインクラスの読み込みを妨げることがあります。

解説 (0)

この場合、次のようになります。

メインクラスを見つけられなかった?クラスパス

これは、「-classpath」を使用しているためですが、ダッシュはコマンドプロンプトの「java」で使用されるダッシュと同じではありません。 この問題はメモ帳からcmdにコピーして貼り付けました。

解説 (1)

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

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
解説 (0)

私の場合、クラス名の代わりにソースファイル名を指定したため、エラーが発生しました。

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

解説 (1)

これは、あなたのケースが特に私のものである場合、あなたを助けるかもしれません:初心者として、私はJavaプログラムを実行しようとしたときにこの問題にも遭遇しました。

このようにコンパイルしました。

javac HelloWorld.java

そして、同じ拡張子でも実行しようとしました。

java Helloworld.java

。javaを削除して java HelloWorldのようなコマンドを書き直すと、プログラムは完全に実行されました。 :)。

解説 (2)

。![ここに画像の説明を入力してください](https://i.stack.imgur.com/eegzM.png。)

クラスファイルの場所: C:\ test \ com \ company。

ファイル名: Main.class。

完全修飾クラス名: com.company.Main。

コマンドラインコマンド:

java  -classpath "C:\test" com.company.Main

ここで、クラスパスには\ com \ companyが含まれていないことに注意してください。

解説 (0)

私はこの問題を解決するためにかなりの時間を費やしました。 どういうわけかクラスパスを誤って設定していると思いましたが、問題は次のように入力したことです。

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

の代わりに:

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

完全に修飾された意味は、完全なパッケージ名ではなくフルパス名を含めることを意味すると思いました。

解説 (2)

まず、このコマンドでパスを設定します。

set path="paste the set path address"

次に、プログラムをロードする必要があります。保存したドライブに "cd (フォルダ名)" と入力し、コンパイルしてください。例えば、私のプログラムがDドライブに格納されている場合、タイプ"D:"Enterキーを押してタイプ"cd(フォルダ名)"です。

解説 (3)

私の場合の問題を解決したのは:

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

[Classpath]タブを開き、[詳細]をクリックします。..ボタンでプロジェクトの**bin`フォルダ**を追加します。

解説 (0)

ここでのすべての回答は、Windowsユーザーに向けられているようです。 Macの場合、クラスパス区切り文字は「:」ではなく「:」です。 ;を使用してクラスパスを設定するエラーがスローされないため、WindowsからMacに取得する場合、これを検出するのは難しい場合があります。

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

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

この例では、パッケージが「com.test」であり、「lib」フォルダーもclasspathに含まれます。

解説 (3)