クラスパスとは
Javaの開発を行っていると、「クラスパス」という用語や「クラスパスを通す」という表現が出てくることがあります。クラスパスとはすなわち「パッケージ構成に沿ってディレクトリに配置されたクラスファイルを検索する際の起点となるディレクトリの候補リスト」であると言えます。
クラスパスに設定されたディレクトリ(またはアーカイブファイル)のリストを先頭から使用し、そこからパッケージと同じ階層のディレクトリを辿った先にあるクラスファイルを、クラスローダが検出するために使用されます。
クラスパスとは
クラスファイル検索の起点となるディレクトリ(およびアーカイブファイル ※後述 )のリスト
クラスパスの必要性
パッケージとディレクトリ構成
クラスパスを知るためには、まずJavaのパッケージついて簡単に理解しておく必要があります。
パッケージの要点のうち、ここで重要となるのは、java
コマンドの引数にはパッケージ名を含む完全修飾クラス名を指定( プログラム実行時のパッケージの使われ方 )し、この時クラスファイルはパッケージと同じ構成のディレクトリに配置される必要がある( 注意点1 )という点です。
例えば C:\Users\java\src
ディレクトリでコマンドプロンプトを開いている場合、次のような com.example
パッケージの Main
クラスは、com\example
ディレクトリに配置する必要があります。
package com.example;
public class Main {
public static void main(String[] args) {
System.out.println("Hello World");
}
}

javac
コマンドはデフォルトでソースファイルと同じ場所にクラスファイルを作成するため、
# ① ソースファイルまでのパスを指定してコンパイル
C:\Users\java\src> javac com\example\Main.java
# ② 完全修飾クラス名を指定して実行
C:\Users\java\src> java com.example.Main
Hello World
という2つの手順を踏むことで、Javaプログラムを正常に実行することができます。
ただ、この状態のままパッケージを増やしていくと、ソースファイルとクラスファイルが様々なディレクトリに混在するようになり、見通しが悪くなってしまいます。そこで、javac
コマンドには、クラスファイルの生成先ディレクトリを指定するためのオプション が用意されています。
この -d
オプション を使用することで、ディレクトリ構造を維持したまま、そのルートとなるディレクトリを別の場所へ切り出すことが可能になります。

しかし、このようにクラスファイルの出力先を変更した場合、java
コマンドによる実行時に問題が発生するようになってしまいます。これは、クラスファイルの出力先を変更したことにより、実行コマンド java com.example.Main
に対し、C:\Users\java\src\com\example\Main.class
が存在しない状態となっているためです。
# ① クラスファイルの出力先ディレクトリを指定してコンパイル
C:\Users\java\src> javac -d ..\bin com\example\Main.java
# ② 完全修飾クラス名と一致するディレクトリのクラスファイルが見つからないためエラー
C:\Users\java\src> java com.example.Main
エラー: メイン・クラスcom.example.Mainを検出およびロードできませんでした
原因: java.lang.ClassNotFoundException: com.example.Main
最も簡単な方法は、cd ../bin
でクラスファイル出力先ディレクトリのルートへ移動してからjava
コマンドを実行することです。実際にこの方法で正常にプログラムを実行できるようになります。しかしこのやり方は、毎回ディレクトリを移動するのが単に面倒なだけでなく、実行時のカレントディレクトリに依存する状態となってしまっているため避けるべきです。
対応するディレクトリの起点
そこで、このような時にクラスパスが役に立ちます。クラスパスとは「クラスファイルを検索するディレクトリ」であり、クラスパスに設定したディレクトリを起点に、パッケージに対応するディレクトリに配置されたクラスが走査されるようになります。
上記の例の場合、クラスパスに C:\Users\java\bin
ディレクトリを設定しておくことで、java com.example.Main
と実行した時に、今いるディレクトリに関係なく、C:\Users\java\bin
を起点に、com.example
パッケージに対応する com\example
ディレクトリが検索され、C:\Users\java\bin\com\example\Main.class
が実行対象になる、という流れです。

このように、パッケージと同じディレクトリ構成を検索する際、どのディレクトリを起点とするべきかを指定するためのパスがクラスパスであり、あるディレクトリをクラスパスに設定することを、しばしば「クラスパスを通す」と表現します。この考え方は、環境変数 PATH
と非常によく似ています。
PATH
についての理解があると、クラスパスの概念も受け入れやすくなります。パッケージの注意点1の補足
前述 したリンク先のページ内では、パッケージの注意点として 階層を合わせる必要がある としていますが、従って厳密にはこの説明ではまだ不足しており「“クラスパスに設定したディレクトリを起点として”、パッケージとクラスファイルの配置ディレクトリとの階層を合わせる必要がある」というのがより正確な表現となります。つまり上記ページでは、対象クラスが com.example.Main
なら、com\example\Main.class
とする必要がある、とは説明しているものの、では com
ディレクトリはどこに配置すべきかというところまでは言及していないということです。
パッケージの最上位階層(ここでは com
ディレクトリ)は必ずクラスパス上に配置する必要があり、逆に言えばパッケージの最上位階層(ここでは com
ディレクトリ)が配置されたディレクトリは必ずクラスパスに設定する必要があります。これが無ければ、クラスローダは起点となるディレクトリが分からず、クラスファイルを1つ検索する度にルート( C:
や /
)からコンピュータ上のあらゆるディレクトリを全て見に行かなくてはならなくなってしまいます。
従って、java
コマンドによるプログラム実行時に、クラスパスの設定は必須となります。ただ、これまでの例では必ずしもクラスパスの設定を行ってきませんでした。これは、明示的な指定がない場合、クラスパスにはカレントディレクトリが設定されるためです。
クラス・パス・オプションが使用されておらず、classpathが設定されていない場合、ユーザー・クラス・パスは現在のディレクトリ(.)で構成されます。
初めの例では、明示的にクラスパスの設定を行わなかったために、C:\Users\java\src
ディレクトリがクラスパスに設定され、C:\Users\java\src\com\example\Main.class
が検索されて java com.example.Main
が正常に実行されたということになります。
クラスパスの設定方法
クラスパスの設定には次の二つの方法があります。
クラスパスの設定方法
java
コマンドのオプションを使用する方法(推奨)- 環境変数
CLASSPATH
を使用する方法
プログラムの実行単位で個別に設定できるため、通常はjava
コマンドのオプションを使用する方法が推奨されます。
クラスパスの設定は、SDK ツールを呼び出すときに
-classpath
オプションを付ける方法 (この方法が望ましい) か、CLASSPATH
環境変数を設定する方法により行います。-classpath
オプションを推奨しているのは、各アプリケーションに対して個別に設定でき、ほかのアプリケーションに影響したり、ほかのアプリケーションからこの値が変更されたりすることがないためです。
オプションを使用する方法
この方法では、java
コマンド実行時にオプションの引数としてクラスパスを直接指定します。
# -cp に続けてクラスパスを指定する。
$ java -cp C:\Users\java\bin com.example.Main
大抵の場合、-cp
オプションが使用されますが、キーワードとしては -cp
の他、--class-path
や -classpath
も用意されています。そのため以下のどれを使用してもクラスパスの指定が可能です。挙動に違いはありません。
$ java --class-path C:\Users\java\bin com.example.Main
$ java -classpath C:\Users\java\bin com.example.Main
$ java -cp C:\Users\java\bin com.example.Main
また、次に説明する環境変数 CLASSPATH
も同時に設定されている場合、オプションで指定したクラスパスの設定が優先されます。
classpathを指定すると、
CLASSPATH
環境変数の設定がオーバーライドされます。
環境変数を使用する方法
推奨は -cp
オプションを使用する方法ですが、アプリケーションや環境ごとにクラスパスを変更したり、その影響を考慮したりする必要がない場合、環境変数 CLASSPATH
を使用することが可能です。これにより、毎回オプションを指定する必要がなくなり、短いコマンド入力でプログラムを実行することができます。
# 環境変数 CLASSPATH にクラスパスを設定
$ set CLASSPATH=C:\Users\java\bin
# 設定した環境変数の値を確認
$ echo %CLASSPATH%
C:\Users\java\bin
# -cp オプションを指定せず実行
$ java com.example.Main
Hello World
複数のパスを設定する場合
ここまでの例では、クラスパスに単一のディレクトリのみを設定してきましたが、;
区切りで複数のディレクトリを設定することも可能です。これにより、例えばユーザ定義クラスは bin
ディレクトリへ、フレームワークやライブラリ等のサードパーティ製クラスは lib
ディレクトリへ格納するといったことが可能になります。( 複数指定 )
またこの時、クラスパスは指定する順序にも意味を持ち、先頭から順に使用される優先順位が高くなります。( 指定の順序 )
これらの点においても、環境変数PATH
と同様の考え方で理解することができます。
クラスパスの活用場面
ディレクトリの共有
クラスパスを通す例として、bin
ディレクトリをここまで例に挙げてきました。これは初めに、ソースファイルとクラスファイルを異なるディレクトリに分けて配置することで、全体の見通しを良くするためであると説明しました。ただしこれはあくまで、いくつかある理由のうちの一つに過ぎません。
ディレクトリを分けるその他の理由としては、チーム開発時のソース共有や、外部ライブラリの利用時に役立つということ等が挙げられます。例えば自分の開発したクラスのまとまりをチームメンバに共有したり、逆に配布されている一連のクラス群を利用したりする際にも、ソースファイルとクラスファイルを分けておくことは有用です。
例として、チーム開発で自分が担当した機能をメンバに共有する場面を考えてみます。この時、メンバにとって必要なのはプログラム実行に必要なクラスファイルだけです。特にクラス数が多い場合など、共有する資源に不要なソースファイルが含まれている状態は避けるべきです。このような場合にも、ディレクトリを分けることが役に立ちます。開発に必要な自分だけが参照できれば良いソースファイルと分けておくことで、実行に必要なクラスファイルだけが含まれたディレクトリを容易にチーム内で連携することができます。
By doing this, you can give the
classes
directory to other programmers without revealing your sources.
こうすることで、ソースを公開することなくクラスディレクトリを他のプログラマに渡すことができます。
また、反対にチーム内の他のプログラマが開発したクラス群を自分が利用したい場合、メンバから貰ったディレクトリの中身を自分のワークスペースにコピーしたりする必要はなく、単にそこへクラスパスを通せばそれで済みます。前述の通りクラスパスには複数のディレクトリを追加することができるため、下の例では、-cp C:\Users\java\bin;C:\Users\java\Downloads\member2pjt\bin
とすることで、実際のディレクトリは異なっていても、Javaプログラム上は、com.example
パッケージ、com.example.util
パッケージと、それぞれ認識できるようになります。
C:
└ Users
└ java
├ src
│ └ com
│ └ example
│ └ Main.java
├ bin
│ └ com
│ └ example
│ └ Main.class
└ Downloads
└ member2pjt ← ダウンロードした物を自分の bin にコピーしたりはせず、
└ bin ← このディレクトリをクラスパスに追加すれば良い。
└ com
└ example
└ util
└ Calculator.class
-cp C:\Users\java\bin;C:\Users\java\Downloads\member2pjt\bin
- ディレクトリ構成
C:\Users\java\bin\com\example\Main.class
C:\Users\java\Downloads\member2pjt\bin\com\example\util\Calculator.class
- 完全修飾クラス名
com.example.Main
com.example.util.Calculator
- ディレクトリ構成
これはチーム内で機能単位の共有を行う際だけでなく、一般に公開されたライブラリを自作クラス内で呼び出すため、自身のプロジェクト内に取り込む場合でも同様です。例えば Apache Commons Lang の場合、ダウンロードページでは「Binaries」と「Source」の二種類が分けて提供されており、必要な方を任意で選択して取得できるようになっています。
- Download Apache Commons Lang
- Binaries
commons-lang3-3.17.0-bin.zip
- Source
commons-lang3-3.17.0-src.zip
- Binaries
Source の方をダウンロードして解凍すると、中身は src\main\java\org\apache\commons\lang3\...
のような構成になっており、様々なソースファイル(.java
)が格納されています。
一方 Binaries はダウンロードして解凍すると、commons-lang3-3.17.0.jar
のようなファイルが含まれています。JARファイルとは、ZIPファイルの一種に過ぎないため、拡張子を .zip
に変更することで、通常のZIPファイルと同様に解凍することができます。
JARファイルは普及しているZIPファイル形式に基づくファイル形式で、多数のファイルを1つにまとめるために使用されます。 JAR ファイルは、基本的にはオプションのMETA-INFディレクトリを格納するZIPファイルです。
このJARファイルを展開すると、中身は org\apache\commons\lang3\...
のような構成になっており、様々なクラスファイル(.class
)が格納されています。
C:
└ Users
└ java
├ src
│ └ com
│ └ example
│ └ Main.java
├ bin
│ └ com
│ └ example
│ └ Main.class
└ Downloads
└ commons-lang3-3.17.0-bin
└ commons-lang3-3.17.0
├ commons-lang3-3.17.0.jar
│ ↓拡張子を書き換え(.jar→.zip)
├ commons-lang3-3.17.0.zip
│ ↓すべて展開...
└ commons-lang3-3.17.0 ← このディレクトリをクラスパスに追加すれば良い。
└ org
└ apache
└ commons
└ lang3
└ ...(.class)
従って、C:\Users\java\Downloads\commons-lang3-3.17.0-bin\commons-lang3-3.17.0\commons-lang3-3.17.0
へクラスパスを通すことで、そこからパッケージを辿れるようになるため、例えば完全修飾クラス名 org.apache.commons.lang3.StringUtils
のような呼び出しが可能となります。
アーカイブファイルの指定
ただし、ここまでに示したJARファイルを解凍してクラスパスに追加する方法は、あまり一般的ではありません。クラスパスには、環境変数PATH
のようにディレクトリパスを追加していくと説明してきましたが、実際にはディレクトリだけでなくアーカイブファイルも設定することができるためです。
開発チーム内でディレクトリを共有する例と、Apache Commons Lang のライブラリを利用する例を2つ挙げました。自分の開発環境となるコンピュータにこれらのディレクトリを配置するにあたり、開発チーム内で共有する際は、ディレクトリをそのままではなく、一度ZIPファイルにまとめてメンバ間で渡しあうことが想定されます。そして Apache Commons Lang では前述の通り、JARファイルの形式でディレクトリをアーカイブしたものが配布されています。
これらにクラスパスを通す際、わざわざ解凍してからそのディレクトリを追加せずとも、クラスパスはディレクトリの他、JARとZIPの形式にそれぞれ対応しているため、そのままファイルパスを追加することができます。
クラス・ファイルを検索するディレクトリ、JARファイルおよびZIPアーカイブのリストを指定します。
そのため、チーム内で共有されたZIPファイルや、Apache Commons Lang からダウンロードしたJARファイルは、いずれも展開することなく、次のように直接クラスパスに追加することが可能です。
$ java -cp C:\Users\java\bin;C:\Users\java\Downloads\member2pjt\bin.zip;C:\Users\java\Downloads\commons-lang3-3.17.0-bin\commons-lang3-3.17.0\commons-lang3-3.17.0.jar com.example.Main
そのため一般にクラスパスを通すといえば、通常はJARファイルのパスを追加することを指します。後述 するEclipseでの設定においても、基本的にはJARファイルの追加手順が多く用いられます。
その他の活用例
このクラスパスの仕組みは、JUnitなどのテストコードからテスト対象クラスを呼び出す際にも有効活用できます。
Eclipseのクラスファイル配置先 でも触れているMavenの標準ディレクトリ構成( Introduction to the Standard Directory Layout )では、製品コードとテストコードのディレクトリを main
/ test
で分けつつ、その下の階層はどちらも同じになるように構成されています。
workspace
└ src
├ main
│ └ java ← workspace\src\main\java にクラスパスを通す。
│ └ com
│ └ example
│ └ Calculator.java
└ test
└ java ← workspace\src\test\java にクラスパスを通す。
└ com
└ example
└ CalculatorTest.java
これにより、実際にクラスファイルが配置されているディレクトリは異なりつつ、Javaプログラムが認識するパッケージは同じになるため、テストクラスから見た対象クラスは同じパッケージに属するクラスとなり、インポート文の記述が不要になります。
package com.example; // 同じパッケージのためテスト対象クラスのインポートは不要
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
class CalculatorTest {
// テスト対象クラス(com.example.Calculator)
private final Calculator calculator = new Calculator();
@Test
void addition() {
int expected = 5;
int actual = calculator.add(2, 3);
assertEquals(expected, actual);
}
}
Eclipseの場合
クラスパスの設定方法 では、-cp
オプションや環境変数を使用する方法を挙げましたが、Eclipseで開発を行っている場合、このことを知っていてもそのまま活用することはできません。EclipseにはEclipseの設定の仕方があるため、裏ではこのようなことが行われているという理解は持ちつつ、設定画面からクラスパスを追加する手順も別に知っておく必要があります。
クラスパスの要点
- クラスパスとは
- クラスファイル検索の起点となる ディレクトリ・ZIP・JAR のリスト
- クラスパスの設定方法
java
コマンドの-cp
オプションでパスを指定(推奨)- 環境変数
CLASSPATH
にパスを設定