トップ 差分 一覧 ソース 検索 ヘルプ RSS ログイン

技術的雑談-Javaコンパイラ・ソースの基礎

技術的雑談-Javaコンパイラ・ソースの基礎


 環境

  • JDK1.4、1.5どっちも。
  • プラットフォーム問わず

 目的

何でJavaのソースはあんなにディレクトリがたくさんあるのか理解する

 内容


Javaではソースについて以下の3つのお約束があります。

  1. ソースファイルは「*.java」、コンパイルされたファイル(classファイル)は「*.class」
  2. 基本的に、ソースのファイル名と中のClass名は同じにする。
  3. ソースの置いてあるディレクトリ階層はClassのPackage階層に合わせる

(ルール3は別に守らなくてもコンパイルは可能ですが、著しくめんどくさくなります。)

ソース、クラス(コンパイルした後の生成物)はpackage(C++で言うところのNamespace)ごとにディレクトリが掘られるのが普通です。

例えば、以下のようなソース構成だったとします。

[ディレクトリ]
./
    /src
        /com
            /hoge
                /fuga
                    TestClass.java
                /mugyo
                    Sub.java
    /bin

[TestClass.java]
package com.hoge.fuga;

public class TestClass {

}

[Sub.java]
package com.hoge.mugyo;

// SubはTestClassを参照している
public class Sub extends com.hoge.fuga.TestClass {

}

この状態で「TestClass」に対して下記のようにjavacを実行すると、

(./ ディレクトリにいる)
javac -sourcepath ./src -d ./bin ./src/com/hoge/fuga/TestClass.java

[ディレクトリ]
./
    /src
        /com
            /hoge
                /fuga
                    TestClass.java
                /mugyo
                    Sub.java
    /bin
        /com
            /hoge
                /fuga
                    TestClass.class

というファイルが作られます。
ディレクトリはコンパイラによって勝手に作られます。

javacコンパイラはコンパイルに必要な依存Classを以下の方法で探してきます。

- 指定されているソースツリー(-sourcepathで示されるディレクトリ以下)
- javacに-classpathで指定されているjar、もしくはディレクトリ
- JDK標準ライブラリー (普通は${JAVA_HOME}/jre/lib以下のjar)

先程生成されたTestClass.classを消して、

javac -sourcepath ./src -d ./bin ./src/com/hoge/mugyo/Sub.java

を実行しても、

[ディレクトリ]
./
    /src
        /com
            /hoge
                /fuga
                    TestClass.java
                /mugyo
                    Sub.java
    /bin
        /com
            /hoge
                /fuga
                    TestClass.class
                /mugyo
                    Sub.class

と、Sub.classだけでなくTestClass.classも作られます。

これは -sourcepath ./srcが指定されているのでコンパイラが自動的にpackage構造を理解して必要なClassを探してくる為です。
その過程でコンパイラはTestClassも依存性があると判断して勝手にコンパイルします。

また、./src/com/hoge/fuga/TestClass.javaがない状態でも、./bin/com/hoge/fuga/TestClass.classがあるなら、

javac -sourcepath ./src -d ./bin -classpath ./bin com/hoge/mugyo/Sub.java

と実行する事により、コンパイラがSub.javaが依存するコンパイル済みのTestClass.classを探してきて、コンパイルを完了します。

上記からもわかるように、-sourcepath、-classpathはその下にあるpackage階層をディレクトリ階層によって理解しますので、ソースもclassもpackageの階層どおりに掘っておく事が望ましいです。

実際は、1つ1つ指定すればソースは階層を無視した状態(例えば、全てのpackageのソースを1つのディレクトリにフラットに置くとか)でもコンパイルは通ります。
しかし、Class毎の依存関係をコンパイラが自動的に判断できない為、ものすごく面倒になります。
(人間が人力で依存関係を解析して、-classpathに与えてやる必要があります。)

 履歴

2005/7/15 -- 初版発行

技術的雑談に戻る

 突っ込み

name   comment  
URL (入力するとす ぱ むとみなします!)


技術的雑談に戻る

TrackBack

TrackBack URL for this entry:
http://www.himajin2001.com/fswiki/tb.cgi/%B5%BB%BD%D1%C5%AA%BB%A8%C3%CC%2DJava%A5%B3%A5%F3%A5%D1%A5%A4%A5%E9%A1%A6%A5%BD%A1%BC%A5%B9%A4%CE%B4%F0%C1%C3

技術的雑談へ戻る

最終更新日時:最終更新時間:2005年07月15日 13時52分38秒
トップページに戻る