入門クラスパス
普段はIDEやビルドツール(MavenやGradle)が影でやってくれているので、あまり意識しないと思います。そもそもクラスパスというものの存在を知らない人も多いのではないでしょうか。
環境
- JDK 21
- macOS 15
コマンドでコンパイル・実行してクラスパスを体験しよう
カレントフォルダがcp-sampleだとします。この直下にcom/example/Main.javaがあるとします。
cp-sample/ <---- 今ここ
└── com
└── example
└── Main.java
package com.example;
public class Main {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}
これをコンパイルするにはjavac .javaファイルの相対パスとします。
cp-sample $ javac com/example/Main.java
先頭の
cp-sample $は、カレントフォルダcp-sampleでjavacコマンドを実行しているを示しています。以下の説明でも同様です。
そうするとクラスファイルMain.classが作られます。
cp-sample/ <---- 今ここ
└── com
└── example
├── Main.class <---- これが作られた!
└── Main.java
これを実行するにはjava クラスの完全修飾名とします。
cp-sample $ java com.example.Main
Hello, World!
これはカレントフォルダcp-sampleで
javaコマンドを実行した結果「Hello, World!」が出力されたことを示します。以下の説明でも同様です。
ではここで、cp-sampleと同じ階層にあるcp-sample2フォルダに移動してみましょう。
cp-sample $ cd ../cp-sample2
.
├── cp-sample
│ └── com
│ └── example
│ ├── Main.class
│ └── Main.java
└── cp-sample2 <---- 今ここ
そして、そこで先程と同じjavaコマンドでMainクラスの実行を試してみます。
cp-sample2 $ java com.example.Main
エラー: メイン・クラスcom.example.Mainを検出およびロードできませんでした
原因: java.lang.ClassNotFoundException: com.example.Main
するとMainクラスが存在しませんというエラーになりました。カレントフォルダのcp-sample2配下にはMain.classが無いので当然ですね。
実は クラスパス を指定すると、cp-sample2がカレントフォルダであってもMainクラスを実行可能です。
cp-sample2 $ java -classpath ../cp-sample com.example.Main
Hello, World!
-classpath オプション( -cp でも同じ意味です)で指定した../cp-sampleがクラスパスです。クラスパスとは、クラスを含むパッケージが入っているフォルダのことです。クラスパスに指定するものはトップレベルパッケージ(今回はcom)を直下に含むフォルダのことです(今回はcp-sampleフォルダ)。
-classpathオプションを指定しない場合はデフォルトでカレントフォルダがクラスパスに追加されます。なので、cp-sampleがカレントフォルダだった時は-classpathオプション無しでも実行できたんですね。
java -classpath ../cp-sample のように、1つでも明示的にクラスパスを指定した場合は、カレントフォルダはクラスパスに追加されませんので注意してください。クラスパスは:で区切って複数のフォルダを指定できますので、カレントフォルダもクラスパスに追加したい場合は java -classpath ../cp-sample:.とします。
Windowsの場合の区切り文字は
;だったと思います。たぶん。
JARファイルの場合は java -classpath JARファイルのパス1:JARファイルのパス2:...とします。
IDEを使った場合
例えばIntelliJでMavenプロジェクトを作成し、以下のようにlogback-classicを依存性に追加します。すると、推移的依存性としてlogbacl-coreとslf4j-apiも追加されます(logback-classicがこれらに依存しているためです)。
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.5.18</version>
</dependency>
</dependencies>

IntelliJからmain()メソッドを実行すると以下のように表示されます。
/Library/Java/JavaVirtualMachines/amazon-corretto-21.jdk/Contents/Home/bin/java ...
-classpath /Users/tada/IdeaProjects/cp-sample-idea/target/classes
:/Users/tada/.m2/repository/ch/qos/logback/logback-classic/1.5.18/logback-classic-1.5.18.jar
:/Users/tada/.m2/repository/ch/qos/logback/logback-core/1.5.18/logback-core-1.5.18.jar
:/Users/tada/.m2/repository/org/slf4j/slf4j-api/2.0.17/slf4j-api-2.0.17.jar
com.example.Main
...
javaコマンドと共に、-classpathオプションがあることが分かりますね!
プロジェクト直下のtarget/classesフォルダにはコンパイルしたクラスファイルが入っているので、このフォルダがクラスパスに追加されています。加えて、~/.m2/repository配下にあるlogback-classic.jarなどのJARファイルもクラスパスに追加されていることが分かります。
これを人間が手作業で書くのは大変なので、IntelliJなどのIDEが自動でやってくれている訳ですね。IDEって便利。
Discussion