以下を記述しました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
は実行できません。
クラス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つの選択肢があります。
あなたの場合、次のように現在のディレクトリを宛先ディレクトリとして指定しても問題ありません(ピリオド.
はcurrent directory)を意味します:
javac -d . Hello.Java
このようにコンパイラを呼び出すと、comディレクトリが作成され、コンパイルされたクラスファイルがJavaプログラムのようにそこに配置されます。それを見つけることを期待しています。次に、上記のようにJavaをc:\ tmpJavaから実行すると、プログラムが実行されます。
パッケージ構造をミラーリングするディレクトリ構造を使用してソースコードをセットアップできます。ソースファイルHello.Javaをcom、あなたの場合: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コードを実行する場合、これはほとんどの場合自動的に処理されますが、クラスパスの問題が発生することに注意してください。
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
クラスはC:\tmpjava\com\Hello.class
にある必要があります
そしてC:\tmpjava
から実行する必要があります:Java -cp . com.Hello
パッケージにクラスを配置すると、クラスのファイル構造が定義されます。つまりパッケージcom
がフォルダーcom
にあるべきクラス
次のコマンドを実行します
Java -cp . com.Hello
Java -classpath c:\ tmpjava com.Hello