Javaのプログラム開発で初心者が躓きやすいポイントに「クラスパス」の設定が挙げられます。
Javaでは開発環境の構築が初心者にとっての最初の難関と言われますが、要因の1つとしてクラスパスを把握出来ていないことが含まれます。
本記事では、Javaで開発する上で知っておくべきクラスパスの設定についてご紹介していきます。
クラスパスとは
クラスパスは、Javaプログラムを実行する際に、Java実行環境がクラスファイルを参照するための場所を指定したものです。
クラスパスはなぜ必要
Javaは、Java Virtual Machine(JVM)と呼ばれる仮想マシン上で実行しますが、実行時に処理内容が記述されたクラスファイルを検索するために必要となります。
Javaの標準APIとして用意されているコアクラスと呼ばれるものは、自動で読み込みが行われるためクラスパスを指定する必要はありませんが、コアクラス以外のクラスファイルに関してはクラスパスを指定して読み込ませてあげる必要があります。
クラスパスの指定方法
クラスパスの指定方法には大きく2通りの方法があります。
classpathオプション
classpathオプションは、コンパイル時や実行時にクラスパスを指定する方法です。
classpathオプションが推奨されることも多く、アプリケーション毎にクラスパスを指定出来るため、他のアプリケーションに影響を与えることがありません。
下記コマンドでクラスパスを設定することが出来ます。
java -classpath クラスパス1[;クラスパス2...] 実行するクラス名;
クラスパスは複数指定することが可能で「;」で区切ります。
先に指定したクラスパスから検索するため、参照の多いファイルがあるパスを先に指定した方が効率的です。
環境変数
クラスパスは環境変数として設定することも可能です。
環境変数に指定したクラスパスは、全てのアプリケーション共通で利用するため注意が必要です。
クラスパス環境変数の指定コマンドは下記となります。
export CLASSPATH=クラスパス1[; クラスパス2...]
環境変数のクラスパス設定をサンプルで確認
実際に順を追ってJavaでのクラスパス設定について確認していきましょう。
クラスパスを確認
まずは環境変数にクラスパスが設定されているかどうかを確認してみます。
現在のクラスパスは、下記コマンドで確認出来ます。
env | grep CLASSPATH
設定されていない場合は何も表示されません。
$ env | grep CLASSPATH $
クラスパスを設定
現在クラスパスが設定されていないようなので、試しに環境変数として設定してみましょう。
$ export CLASSPATH=/usr/local/bin/ $
先程の確認コマンドを実行すると、設定したパスがクラスパスとして表示されます。
$ env | grep CLASSPATH CLASSPATH=/usr/local/bin/
クラスパスを解除
先程設定したクラスパスを解除してみます。
$ unset CLASSPATH
確認コマンドを実行すると、設定したクラスパスが解除されているのが分かります。
$ env | grep CLASSPATH $
オプションのクラスパス設定をサンプルで確認
次は環境変数ではなく、オプションでクラスパス設定をする方法をサンプルで確認してみます。
サンプルコード
1つ目のサンプルコードは「書類」→「sample」フォルダの中に「Main.java」というファイルを下記内容で格納しておきます。
Main.java
public class Main { public static void main(String args[]) { Sub sub = new Sub(); System.out.println(sub.content); } }
2つ目のサンプルコードは「書類」→「sample」→「subDir」フォルダの中に「Sub.java」というファイルを下記内容で格納しておきます。
Sub.java
public class Sub { String content = "Subクラスで設定しました。"; }
コンパイル
別階層に関連するファイルがある場合、クラスパスを指定せずにコンパイルしようとするとエラーとなってしまいます。
$ javac Main.java Main.java:3: エラー: シンボルを見つけられません Sub sub = new Sub(); ^ シンボル: クラス Sub 場所: クラス Main Main.java:3: エラー: シンボルを見つけられません Sub sub = new Sub(); ^ シンボル: クラス Sub 場所: クラス Main エラー2個
これはクラスパスを指定していないことにより、「Main.java」ファイルの格納されている同フォルダしかデフォルトでは参照しないため起きるエラーです。
次はクラスパスを「Sub.java」が格納されたディレクトリに指定して、コンパイルを実施してみましょう。
$ javac -classpath ./subDir/ Main.java $ ls Main.class Main.java subDir
エラーが起きずにコンパイル出来ているのが分かります。
クラスパスを指定する「./subDir/」は、現在のフォルダ配下の「subDir」フォルダを指定しています。
実行時
クラスパスの指定はコンパイル時だけでなく、実行時にも指定しないとエラーが発生してしまいます。
$ java Main Exception in thread "main" java.lang.NoClassDefFoundError: Sub at Main.main(Main.java:3) Caused by: java.lang.ClassNotFoundException: Sub at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:583) at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178) at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521) ... 1 more
ではsubDirフォルダに格納されているclassファイルも参照出来るようにクラスパスを指定して実行してみましょう。
$ java -classpath .:subDir/ Main Subクラスで設定しました。
「.:subDir/」の記述で、カレントディレクトリとsubDirフォルダを参照するように指定しています。
さいごに: Javaではクラスパスの設定が必須
本記事では、Javaプログラミングの初心者が躓きやすいクラスパスについて、基本的な情報と設定方法をご紹介してきました。
初心者がJavaプログラムの開発で全く実行出来ない際、よく忘れがちなのがクラスパスの設定です。
今回ご紹介した内容を参考に、Javaプログラムが実行出来ない場合には、クラスパスの設定忘れがないか確認してみてください。
記事内で紹介していくコマンドはMac環境を想定しています。
Windows環境と異なる部分もあるため、Windowsユーザーの方は適宜コマンドを読み替えてください。