コマンドプロンプトでjavaを実行する場合に、NoClassDefFoundErrorとなり最初つまづきました。原因はクラスパスやクラスの完全名を間違えていたためでした。この記事でNoClassDefFoundErrorの時の対処法をまとめました。
環境
Windows10
Java version 17.0.3.1
NoClassDefFoundError とは
Java仮想マシンまたはClassLoaderインスタンスがクラス定義をロードしようとしたが、クラス定義が見からない場合にスローされます。(公式ドキュメントより)
この説明を理解してくと、クラスパスやクラスの完全名について理解が進みました。
Java仮想マシンとは
Javaプログラムを実行するためのソフトウェア。 Javaバイトコードで記述されたコンピュータプログラムを解釈し、そのコンピュータで実行可能な形式のコードに変換して実行する。
ClassLoaderインスタンスとは
クラスのロードやリソース(ファイル)の検索を担当するオブジェクト
クラス定義とは
変数を宣言し、オブジェクトが持つメソッドやプロパティが呼び出されたときに実行されるコードを記述した一連のコードを「クラス」あるいは「クラスの定義」と呼びます。
つまり
NoClassDefFoundError は、「Javaバイトコード(中間コード。JVMによって実行可能な機械語になる前に、コンパイルされてできたバイナリデータ)をJVMが解釈しようとするが、実行するべきクラスをロードできていない」というエラーです。
ここでクラスパスが出てくる
なぜJVMがクラスをロードできないのでしょうか。
それはクラスがどこにあるか=クラスパスをJVMに明確に教えてあげる必要があるからです。
クラスパスとは
クラスパスは、Java 実行環境がクラスおよび他のソースファイルを検索するパスです。
つまり、クラスが存在するパスを指定して実行する必要があります。
クラスパスの指定のしかた
java
コマンドの後に -classpath
+ クラスパスを指定します。
> java -classpath <クラスパス>
重要なことは、クラスパス=クラスが含まれるパッケージ(フォルダ)の親フォルダだということです。
大体は、OO.java
ファイルが入ったフォルダがパッケージとなります。コマンドプロンプトでコンパイルしたら、そのパッケージにクラス(OO.classファイル
)も入ります。そのパッケージの親フォルダをクラスパスに指定します。
例えば、C:\...\hoge\fuga\foo.java
のパッケージは fuga
とします。その親フォルダは hoge
なので、
クラスパスは C:\...\hoge
になります。
> java -classpath C:\...\hoge
ここでまだ完成ではありません。最後にクラス名を指定します。
クラスパスを指定したら(完全)クラス名を指定する
さっきの例の C:\...\hoge\fuga\
パッケージに foo.class
が出来ていたとします。java
コマンドで指定するクラスは、完全クラス名です。完全クラス名とは、「パッケージのフォルダ名+ .(ドット) +クラスファイル名」です。
> java -classpath C:\...\hoge fuga.foo