web-dev-qa-db-ja.com

Javaメインクラスが見つかりません

以下を記述しましたJavaソースファイル(Hello.Java):

package com;

public class Hello {
    public static void main(String[] args) {
        System.out.println("Hello!");
    }
}

これをC:/tmpjava/Hello.Javaに保存します。

コマンドラインから、そのディレクトリに移動し、javac Hello.Javaを実行します。次に、dirを実行します。

  • Hello.class
  • Hello.Java

次に、javacを実行したディレクトリと同じディレクトリからJava Hello.classを実行し、以下を取得します。

Exception in thread "main" Java.lang.NoClassDefFoundError: Hello/class
Caused by: Java.lang.ClassNotFoundException: Hello.class
    at Java.net.URLClassLoader$1.run(URLClassLoader.Java:202)
    at Java.security.AccessController.doPrivileged(Native Method)
    at Java.net.URLClassLoader.findClass(URLClassLoader.Java:190)
    at Java.lang.ClassLoader.loadClass(ClassLoader.Java:306)
    at Sun.misc.Launcher$AppClassLoader.loadClass(Launcher.Java:301)
    at Java.lang.ClassLoader.loadClass(ClassLoader.Java:247)
Could not find the main class: Hello.class.  Program will exit.

何が起きてる?!? javacは正常に実行できますが、Javaは実行できません。

19
IAmYourFaja

クラスHelloはパッケージcomに属します。したがって、クラスの完全修飾名はcom.Helloです。コマンドラインでJavaを使用してプログラムを呼び出す場合、mainメソッドを含むクラスの完全修飾クラス名を指定し、.class、次のように:

Java com.Hello

Javaプログラムでは、参照しているクラスを理解するために、この完全修飾クラス名が必要です。

しかし、別の問題があります。 Javaプログラムは、ファイルシステムを使用して、パッケージ、サブパッケージ、およびそれらに属するクラスを見つけます。したがって、com.Helloのようなパッケージ構造がある場合、Javaプログラムは、Hello.classという名前のクラスファイルがcom、このように:com/Hello.class。実際、Exceptionでこの動作を確認できます。誤って使用しているHello.class、JavaはHello、およびclassという名前のclass、およびディレクトリ構造Hello/classを探しています:

Java.lang.NoClassDefFoundError:Hello/class

ただし、コンパイラjavacはデフォルトではこのディレクトリ構造を設定しませんjavacのドキュメント を参照してください。ただし、重要な点は次のとおりです。コンパイルを行うとき、-dフラグを使用して宛先ディレクトリを指定できます。

-dディレクトリ

クラスファイルの宛先ディレクトリを設定します。宛先ディレクトリはすでに存在している必要があります。 javacは、宛先ディレクトリを作成しません。クラスがパッケージの一部である場合、javacはパッケージ名を反映するサブディレクトリにクラスファイルを配置し、必要に応じてディレクトリを作成します。たとえば、-d c:\ myclassesを指定し、クラスの名前がcom.mypackage.MyClassの場合、クラスファイルの名前はc:\ myclasses\com\mypackage\MyClass.classになります。

-dが指定されていない場合、javacはクラスファイルをソースファイルと同じディレクトリに配置します。

太字の最後のビットは、初心者にとって大きな混乱の原因であり、あなた自身の問題の一部です。

したがって、2つの選択肢があります。

  1. あなたの場合、次のように現在のディレクトリを宛先ディレクトリとして指定しても問題ありません(ピリオド.current directory)を意味します:

    javac -d . Hello.Java
    

    このようにコンパイラを呼び出すと、comディレクトリが作成され、コンパイルされたクラスファイルがJavaプログラムのようにそこに配置されます。それを見つけることを期待しています。次に、上記のようにJavaをc:\ tmpJavaから実行すると、プログラムが実行されます。

  2. パッケージ構造をミラーリングするディレクトリ構造を使用してソースコードをセットアップできます。ソースファイルHello.Javacom、あなたの場合:c:\ tmpJava\com\Hello.Java。これで、c:\ tmpJavaから、次のようにjavacコンパイルを実行できます。

    javac com\Hello.Java
    

    -dフラグを指定していませんが、ディレクトリ構造を自分で作成し、上記のドキュメントから再度引用しているため、問題ありません。

    -dが指定されていない場合、javacはクラスファイルをソースファイルと同じディレクトリに配置します。

    繰り返しますが、上記のようにJavaを実行すると、プログラムが実行されます。

    この2番目の選択肢は、Javaプログラマーがよく使用するものであることに注意してください。ソースコードファイルは、パッケージ構造を反映したディレクトリ構造に編成されています。

この説明では、classpathの概念を無視しました。 Javaプログラムを作成することも理解する必要がありますが、現在のディレクトリでプログラムを単にコンパイルする場合-クラスをコンパイルするときに上記の2つの選択肢のいずれかに従うと、次のようになります。デフォルトでは、Javaプログラムにはクラスパスとして現在のディレクトリがあるため、クラスパスを設定せずに離れます。別の引用、これは Javaのドキュメント

-cpクラスパス

ディレクトリ、JARアーカイブ、およびZipアーカイブのリストを指定して、クラスファイルを検索します。クラスパスエントリはセミコロン(;)で区切られます。 -classpathまたは-cpを指定すると、CLASSPATH環境変数の設定がオーバーライドされます。

-classpathと-cpが使用されず、CLASSPATHが設定されていない場合、ユーザークラスパスは現在のディレクトリ(。)で構成されます。

EclipseのようなIDEを使用してJavaコードを実行する場合、これはほとんどの場合自動的に処理されますが、クラスパスの問題が発生することに注意してください。

43
pb2q

Javaコマンドの構文は次のとおりです。

Java [classname]

not

Java [filename]

Javaはclasspathで、指定した名前のクラスを探します。通常、クラスパスには現在のディレクトリが含まれます。

Java Hello

...現在のディレクトリでHello.classを見つけ、そのmain()メソッドを実行します。

ただし、クラスが別の場所(.jarやファイルシステムの別の場所など)にある場合は、CLASSPATH環境変数またはコマンドラインで指定できます。

Java -cp build/classes Hello
Java -cp build/jars/myjar.jar Hello
9
slim

クラスはC:\tmpjava\com\Hello.classにある必要があります
そしてC:\tmpjavaから実行する必要があります:Java -cp . com.Hello
パッケージにクラスを配置すると、クラスのファイル構造が定義されます。つまりパッケージcomがフォルダーcomにあるべきクラス

4
Cratylus

次のコマンドを実行します

Java -cp . com.Hello
2
SiB

Java -classpath c:\ tmpjava com.Hello

1
StephenMeyer