CLASSPATHの役割
 

importとpackageの仲を取り持つCLASSPATH

CLASSPATHは、コンパイルする時にも実行する時にも使われます。
その目的は、皆さんが作ったクラスの中で利用している他のクラスがどこにあるかを、 javacやjavaコマンドなどに教えることです。

例えば、JDBCドライバ自体はJDKに入っていないので、 RDBベンダーが提供するドライバを利用することになります。そのドライバが入っているファイルはどれ? という情報を設定するのがCLASSPATHというわけです。Windowsの場合は、
set CLASSPATH=C:\orant\lib\classes12.zip
というように設定します。
複数のファイルを指定したい場合は;(セミコロン)(UNIXの場合は:(コロン))で区切ります。
set CLASSPATH=C:\orant\lib\classes12.zip;D:\tomcat\lib\crimson.jar
という要領です。

先程のpackageを追加したHelloWorld2クラスがコンパイルに失敗したのは、 CLASSPATHが設定されていないことが原因です。 つまり、HelloWorld2クラスの中で利用(参照)しようとしているMessageクラスがおらんっ!! と怒られたんです。
でも、Messageクラスは自分で作ったクラスだし、zipファイルやjarファイルの中になんかありませんよね? 一体どうやって指定するんでしょうか?
実はCLASSPATHではファイルだけでなく、ディレクトリも指定出来るようになっています。
MessageクラスやHelloWorld2クラスがあるディレクトリは、
C:\Source\Java\
┣━otamesi
┗━test
という構成になっています。ですからCLASSPATHに次のように設定します。
CLASSPATH大明神お参り の図
C:\Source\Java\test>set CLASSPATH=c:\source\java

C:\Source\Java\test>

                        
ほんとに設定出来たかを確認しましょう。
CLASSPATH大明神のお札を頂く の図
C:\Source\Java\test>set CLASSPATH
CLASSPATH=c:\source\java

C:\Source\Java\test>
                        
ここで再びコンパイルしてみます。
CLASSPATH大明神の神通力 の図
C:\Source\Java\test>javac HelloWorld2.java

C:\Source\Java\test>
                        
うぉぉぉぉぉぉ、コンパイルが通ったじゃー!!!
この勢いで実行ですじゃ。
CLASSPATH大明神の神通力が通じない?! の図
C:\Source\Java\test>java HelloWorld2
Exception in thread "main" java.lang.NoClassDefFoundError: HelloWorld2

C:\Source\Java\test>
                        
なにぃぃぃぃぃぃっ?! なんで、なんでぇぇぇぇ?!
CLASSPATHが通じないなんて....... HelloWorld2クラスがNoClassDefFoundErrorだとっ?!

いや、ちょっと待てよ、HelloWorld2クラスから見たMessageクラスへの参照は解決したけど、 HelloWorld2そのもに付けたpackagetestだったぞ。 ということはHelloWorld2クラスの正しいパッケージ表現はtest.HelloWorld2のはず。
そのtestの直前までのパスはCLASSPATHc:\source\javaと設定したわけだから んじゃぁ、これでどうじゃ!
CLASSPATH大明神はやっぱりすごかった の図
C:\Source\Java\test>java test.HelloWorld2
Hello world!

C:\Source\Java\test>
                        
ひょぇぇぇぇぇ、実行できたじゃー!!!

そうです。HelloWorld2クラス自体がどこにあるかはimportコマンドで指定することが出来ないので、 パッケージ名付きでクラスを指定しないとjavaコマンドが実行出来なかったんです。

私はJavaで開発する複数のプロジェクトをかけもちしています。 その場合CLASSPATHに複数のディレクトリを指定するといずれのプロジェクトのクラスも参照出来るようになります。
set CLASSPATH=C:\Project\えっくす;C:\Project\さんでー

「えっくす」プロジェクトでmemberというパッケージを作り、 その中にShikaishaというクラスがあったとします。
C:\Project\えっくす\
┗━member\
┗━Shikaisha.class
という構成になっています。
クラスの中はこんな感じです。
ご存じお休み中の「くぼじゅん」です
package member;

/**
 *  プロジェクトえっくすの司会者クラスでーす
 *  @author YTP
 */
public class Shikaisha {
    /**
     *  コンストラクタでーす
     */
    public Shikaisha() {
    }
    
    /**
     *  司会者が挨拶をします
     */
    public void greet() {
        System.out.println("皆さんこんばんは、久保純子でーす");
    }
}
                        
「えっくす」司会者に挨拶をさせるクラス
package test;

import member.*;

/**
 *  司会者に挨拶をしていただきましょう!
 *  @author YTP
 */
public class HelloMC {
    public static void main(String[] args) {
        // くぼじゅんさん出番でーす
        Shikaisha kubojun = new Shikaisha();
        kubojun.greet();
    }
}
                        
実行すると次のようになります。
はやく復帰しないかな の図
C:\Project\えっくす\test>java test.HelloMC
皆さんこんばんは、久保純子でーす

C:\Project\えっくす\test>
                        

かけもちしているプロジェクトは「さんでー」です。
このプロジェクトでは、先の「えっくす」で作ったクラスをちょこっと修正して利用しようと考えました。
新たに考えるのが面倒くさいのでパッケージ名やクラス名はおんなじでいきます。
C:\Project\さんでー\
┗━member\
┗━Shikaisha.class
という構成になっています。
クラスの中はこんな感じです。
最近やたらまるくなった「しんすけ」です
package member;

/**
 *  プロジェクトさんでーの司会者クラスでーす
 *  @author YTP
 */
public class Shikaisha {
    /**
     *  コンストラクタでーす
     */
    public Shikaisha() {
    }
    
    /**
     *  司会者が挨拶をします
     */
    public void greet() {
        System.out.println("皆さんおはようございます、伸助です");
    }
}
                        
「さんでー」司会者に挨拶をさせるクラス
package test;

import member.*;

/**
 *  司会者に挨拶をしていただきましょう!
 *  @author YTP
 */
public class HelloMC {
    public static void main(String[] args) {
        // 伸助さん出番でーす
        Shikaisha shinsuke = new Shikaisha();
        shinsuke.greet();
    }
}
                        
実行すると次のようになります。
えっ、くぼんじゅんが転職復帰?! の図
C:\Project\さんでー\test>java test.HelloMC
皆さんこんばんは、久保純子でーす

C:\Project\さんでー\test>
                        
なんじゃこりゃ? なんで伸助が出て来ないのぉ? 目が(・_・)です。

実はこれ、CLASSPATHの副作用です。CLASSPATHの設定を確認してみましょう。
えっ、くぼんじゅんが転職復帰?! の図
C:\Project\さんでー\test>set CLASSPATH
CLASSPATH=C:\Project\えっくす;C:\Project\さんでー

C:\Project\さんでー\test>
                        
えっくすが先に書いてありますね。
そのためjavaコマンドは先に見つかったC:\Project\えっくすの中のtest.HelloMCクラスを実行します。
試しにCLASSPATHの順を逆にして実行してみましょう。
冗談のようなほんとの話!! の図
C:\Project\さんでー\test>set CLASSPATH=C:\Project\さんでー;C:\Project\えっくす

C:\Project\さんでー\test>java test.HelloMC
皆さんおはようございます、伸助です

C:\Project\さんでー\test>
                        
ちゃんと伸助さんが挨拶してくれました。

さて、じゃぁ、私のようにこき使われる悲しきかけ持ち社員はどのようにしたらいいんでしょう?!
毎回 set CLASSPATHってやるのぉ?
いえいえ 解決策はちゃんとあります。しかも二通りもっ!!

■その一 オプション指定
javacやjavaには実行時にCLASSPATHを指定出来るようにちゃんとオプションが用意されています。
javac あるいは java -h
と実行するとそれぞれのオプションが確認出来ます。
javaの場合は-cpというオプションがそれです。やってみましょう。
くぼじゅん復帰はまだ先 の図
C:\Project\さんでー\test>set CLASSPATH=C:\Project\えっくす;C:\Project\さんでー

C:\Project\さんでー\test>java test.HelloMC
皆さんこんばんは、久保純子でーす

C:\Project\さんでー\test>java -cp C:\Project\さんでー test.HelloMC
皆さんおはようございます、伸助です

C:\Project\さんでー\test>
                        

■その二 CLASSPATHでのピリオドの利用 ←YTPのお薦め
CLASSPATHに.(ピリオド)を指定すると、 javacやjavaはカレントディレクトリを起点にパッケージを探してくれます。 つまり、現在扱っているプロジェクトのディレクトリのみを相手にしてくれるようになるんです。
ピリオドも試してみんとす の図
C:\Project\さんでー\test>set CLASSPATH=.

C:\Project\さんでー\test>java test.HelloMC
Exception in thread "main" java.lang.NoClassDefFoundError: test/HelloMC

C:\Project\さんでー\test>
                        
なにぃー、うそつきーっ! またエラーがでたやんけー!

ちょっと待って下さい、メッセージをよく読みましょう。
NoClassDefFoundError: test/HelloMC となっています。
CLASSPATHにピリオドを書くとそれはカレントディレクトリを意味するって言いましたよね? カレントディレクトリは今どこですか? そう、C:\Project\さんでー\test です。
ここにはtest/ なんてディレクトリがあるはずがありません。だって今そこにいるんだものっ!
だったら.....
ピリオドに感謝 の図
C:\Project\さんでー\test>cd ..

C:\Project\さんでー>java test.HelloMC
皆さんおはようございます、伸助です

C:\Project\さんでー\test>
                        

ピリオドが便利なのはここからです
ディレクトリを変更すれば-cpオプションなんくぁっまったく必要ありませんぜっ、だんなっ!
ピリオド様に大感謝 の図
C:\Project\さんでー>cd ..\えっくす

C:\Project\えっくす>java test.HelloMC
皆さんこんばんは、久保純子でーす

C:\Project\えっくす>
                        

ピリオドを使うとコンパイルのときにももちろん有効です
コンパイルしたいクラスがimportしている他のクラスを、 カレントディレクトリを基準にして探しに行きます。
ピリオド様はコンパイルもお手の物 の図
C:\Project\えっくす>javac test\HelloMC.java

C:\Project\えっくす>
                        
コンパイル対象のファイルにはカレントディレクトリからの相対パスも指定していることに注意して下さい。

CLASSPATHって?に戻ります。


Copyright © 2002-2016, Your Technology Partner. All rights reserved.