Bits of Java (トップ)

VM   JDK と JRE
Language   オブジェクトとインスタンス   this と super   static   フィールドアクセス
IO   Serializable の実装
Swing   MetalLookAndFeel   イメージパネル
JavaBeans   プロパティ名について   XMLEncoder で保存
その他   正規表現テストアプリ   秀丸の強調表示   Ant のインストール   文字セット変換 Ant タスク   XAMPP + Tomcat

JDK と JRE の両方をインストールしている際の ext ディレクトリについて

JDK は Java の開発環境でコンパイラをはじめとする様々なツールを含み Java プログラムを実行することができます。 複数のバージョンの JDK をインストールしていても、コンパイルに使用した JDK で Java プログラムを実行すればバージョン違いの不整合などは発生しません。 JRE は実行環境のみを提供し、インストールすると Java Plug-In によるアプレットの実行や Java Web Start が使えるようになります。 JRE の方は1つしかインストールできず、複数のバージョンを使い分けるという事はできません。 JRE はそのバージョンが古い為にアプレットなどが実行できなかったり、新しいバージョンでバグフィックスが行われている場合などがあるので、常に最新のバージョンが推奨され、自動的にネットでチェックして新しいバージョンがあれば更新可能であることをユーザに通知するのがデフォルトの設定になっています。 (Java コントロールパネルで設定を変更できます)

Windows に JDK をインストールする際にデフォルトの設定では JRE もインストールされます。 例えば WindowsXP に jdk1.5.0_09 をインストールするとデフォルトでは JDK が C:\Program Files\Java\jdk1.5.0_09 にインストールされ、JRE の方は C:\Program Files\Java\jre1.5.0_09 にインストールされます。 この場合に C:\Program Files\Java\jdk1.5.0_09\jre ディレクトリ以下と C:\Program Files\Java\jre1.5.0_09 ディレクトリ以下はほとんど同じ内容になっています (JDK と違い JRE の方にはサーバモードの JVM がなく Java プログラム実行時に標準オプションの -server を指定するとエラーになります)。 同じファイル群が2つ存在することになりますが、これは JRE が JDK とはまったく別に存在する独立した Java 実行環境である為です。 また JRE は新しいバージョンが公開されれば直ちに更新されるべきものなので、この状態がずっと続くとは限りません。

このような JDK と JRE の2つの実行環境が存在する場合に拡張パッケージをインストールする際にはどちらの ext ディレクトリに配置するべきなのか疑問に思い、調べてみました。 以下 JDK をインストールした方のディレクトリを JAVA_HOME とし、 JRE をインストールした方を JRE_HOME とします。

JRE は開発環境は含みませんのでコンパイル時には常に JDK の方の JAVA_HOME/jre/lib/ext の方が有効となります。

実行時の方は JAVA_HOME/bin/java.exe と JRE_HOME/bin/java.exe の実行された方の ext ディレクトリが有効になります。 またシステムプロパティ java.home の値も実行された方が有効になります。 JAVA_HOME/bin/java.exe を実行した場合に以下のコードは
System.getProperty("java.home");
JAVA_HOME/jre ディレクトリのパスを返し、 JRE_HOME/bin/java.exe を実行した場合には JRE_HOME が表すディレクトリのパスを返します。

どちらの java.exe が実行にされるのかに関しては次のように動作します。 例えば WindowsXP にバージョン 1.5.0_09 の JDK と JRE がインストールされており、環境変数 JAVA_HOME に C:\Program Files\Java\jdk1.5.0_09 を設定し、 PATH には %JAVA_HOME%\bin を含めている環境でコマンドラインから
java -verbose > a.log
を実行したとします。 この場合にカレントディレクトリに出力された a.log の内容を見ると JRE_HOME/bin/java.exe が実行されているのがわかります。 環境変数 PATH に %JAVA_HOME%\bin を設定しているので JAVA_HOME/bin/java.exe が実行されるような気がしますが、 JRE をインストールしている場合には java や javaw というコマンドは JRE_HOME/bin にある方が実行されます。(JRE がインストールされていない場合には PATH から java や javaw コマンドを探し %JAVA_HOME%\bin にある方が実行されます)

パスを指定して JDK の方を実行してみると
"C:\Program Files\Java\jdk1.5.0_09\bin\java" -verbose > b.log
この場合にはちゃんと JAVA_HOME/bin/java.exe が実行されているのが b.log の内容から分かります。

よって JRE をインストールしている場合にコマンドラインから単に java と入力して実行した場合には JRE の java.exe が実行されるので有効な ext ディレクトリは JRE_HOME/lib/ext の方となります。
またパスを指定して JAVA_HOME/bin/java.exe を実行した場合には JAVA_HOME/jre/lib/ext ディレクトリが有効になります。 Tomcat などのように bat ファイルを使って起動するプログラムの場合は 環境変数 JAVA_HOME を使用して JAVA_HOME/bin/java.exe を実行する場合が多いようです。

結論としては実行時に両方の java.exe (あるいは javaw.exe)が使われる可能性があり、実行された方の ext ディレクトリが有効になる以上、 JDK と JRE の両方をインストールしている環境で JAR ファイルを ext ディレクトリに配置する場合には、 JAVA_HOME/jre/lib/ext と JRE_HOME/lib/ext の両方に配置するのが JDK と JRE を区別しながら管理するよりも簡単だと思います。 JAVA_HOME/jre/lib や JRE_HOME/lib にある properties ファイルの設定など lib ディレクトリ以下のリソースの設定も同様です。

最後になってしまいましたが 個人的には拡張パッケージ(JAR ファイル)を ext ディレクトリにインストールしないようにしています。 ext ディレクトリに配置した拡張パッケージを管理するのが面倒だからです。 例えば、あるプログラムを実行する為に必要なライブラリである hoge.jar を ext ディレクトリに配置し、 かなりの時間が経過してから新しいバージョンの hoge.jar を使うプログラムを作成または実行する事になったとします。 この場合に ext ディレクトリの古い方を新しい方に置き換えた場合には古い方の hoge.jar を使っていた方のプログラムが動かなくなる可能性があります。 また ext ディレクトリの hoge.jar の事をすっかり忘れて、新しい方の hoge.jar にクラスパスを通して使用した場合には、実際にクラスローダによってロードされるのは ext ディレクトリの hoge.jar の方なのでプログラムが予想外の動作やエラーや起こしてしまうかもしれません。 自分では新しい方の hoge.jar を使っていると思っているので原因の特定に時間がかかるかもしれません。 Eclipse など IDE を使っている場合にはコンパイル時やプログラム実行時のクラスパスの設定が簡単に行えるのであえて ext ディレクトリを使う必要は無いと思われます。