読者です 読者をやめる 読者になる 読者になる

謎なMacのJavaインストール構成

Java Mac

先日、ようやくMac版JDK7のGA版が登場しました。今までMacJDKAppleが提供していましたが、7からはOracleからの提供となります。
早速インストールしたのですが、実に奇妙な現象が見られたのでここに記録しておきます。

インストールはOracleのダウンロードサイトからダウンロードしたインストーラを使ってインストールします。特に難しいことはなく、指示に従ってインストールするだけです。

インストール後、JDK7をデフォルトのJDKにするには設定変更が必要です。ここで説明されているのですが、/Applications/Utilities/Java Preferences.app を起動し、以下のスクリーンショットのように [Java SE7] をドラッグして一番上に持って行きます。

これでJDK7がデフォルトで有効になるはず、なのですが自分の環境ではそうなりませんでした...。

$ java -version
java version "1.6.0_31"
Java(TM) SE Runtime Environment (build 1.6.0_31-b04-415-11M3635)
Java HotSpot(TM) 64-Bit Server VM (build 20.6-b01-415, mixed mode)

その時は一旦あきらめたのですが、後日、ふと .bash_profile に環境変数 JAVA_HOME を設定しており、そこで JDK6 のインストールパスを指定していたことを思い出しました。そこで、JAVA_HOME の設定を削除して、シェルを再度開いて確認してみると...

$ java -version
java version "1.7.0_04"
Java(TM) SE Runtime Environment (build 1.7.0_04-b21)
Java HotSpot(TM) 64-Bit Server VM (build 23.0-b21, mixed mode)

ちゃんとJDK7を認識しています! これで晴れて自分のMac環境もJDK7環境になりました。

しかし疑問が残ります。JAVA_HOME は設定していましたが、パスはそこには通していませんでした。実際、環境変数を変更した前後で "which java" をしても /usr/bin/java を指しています。
まず、/usr/bin/java の実体を調べてみます。

$ ls -li /usr/bin/java
40738383 lrwxr-xr-x  1 root  wheel  74  4 15 20:59 /usr/bin/java -> /System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands/java

/System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands/javaシンボリックリンクが貼られています。
で、パスの途中に出てくる "Current" というディレクトリですが、以下のように "A" というディレクトリに対するシンボリックリンクとなっています。

$ ls -li
total 64
40738298 lrwxr-xr-x  1 root  wheel   10  4 15 20:59 1.4 -> CurrentJDK
40738299 lrwxr-xr-x  1 root  wheel   10  4 15 20:59 1.4.2 -> CurrentJDK
40738300 lrwxr-xr-x  1 root  wheel   10  4 15 20:59 1.5 -> CurrentJDK
40738301 lrwxr-xr-x  1 root  wheel   10  4 15 20:59 1.5.0 -> CurrentJDK
40738302 lrwxr-xr-x  1 root  wheel   10  4 15 20:59 1.6 -> CurrentJDK
40738303 lrwxr-xr-x  1 root  wheel   10  4 15 20:59 1.6.0 -> CurrentJDK
24547503 drwxr-xr-x  8 root  wheel  272  4 15 21:56 A
40739474 lrwxr-xr-x  1 root  wheel    1  4 15 20:59 Current -> A
40738356 lrwxr-xr-x  1 root  wheel   59  4 15 20:59 CurrentJDK -> /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents

この A という名前のディレクトリですが、Mac上にフレームワーク環境を構築する際には、複数のバージョンを入れておきたい場合は、A, B, C... というアルファベット順のディレクトリを作って、そこに異なるバージョンを入れるようにするという慣習になっているようです (Appleの解説はここ) 。
で、A/Commands の中を覗いてみると次のようになっていました。

$ ls -li A/Commands
total 1280
40738305 -rwxr-xr-x  1 root  wheel  54272  4 15 20:59 appletviewer
40738306 -rwxr-xr-x  1 root  wheel  54272  4 15 20:59 apt
40738307 -rwxr-xr-x  1 root  wheel  54272  4 15 20:59 extcheck
40738308 -rwxr-xr-x  1 root  wheel  54272  4 15 20:59 idlj
40738309 -rwxr-xr-x  1 root  wheel  54272  4 15 20:59 jar
40738310 -rwxr-xr-x  1 root  wheel  54272  4 15 20:59 jarsigner
40738311 -rwxr-xr-x  1 root  wheel  54272  4 15 20:59 java
40738312 -rwxr-xr-x  1 root  wheel  67456  4 15 20:59 java_home
...

リンクではなく、実ファイルのようです。もしかしてハードリンクなのかな?と思ったのですが、JDK7のコマンドディレクトリに入っている java を確認してみると...

$ ls -li /Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/bin
total 6888
41515326 -rwxrwxr-x  1 root  wheel  88864  4 20 14:58 appletviewer
41515327 -rwxrwxr-x  1 root  wheel  88864  4 20 14:58 apt
41515328 -rwxrwxr-x  1 root  wheel  88864  4 20 14:58 extcheck
41515329 -rwxrwxr-x  1 root  wheel  88864  4 20 14:58 idlj
41515330 -rwxrwxr-x  1 root  wheel  88864  4 20 14:58 jar
41515331 -rwxrwxr-x  1 root  wheel  88864  4 20 14:58 jarsigner
41515332 -rwxrwxr-x  1 root  wheel  88800  4 20 14:58 java
41515333 -rwxrwxr-x  1 root  wheel  88864  4 20 14:58 javac
...

実体が違うようですし、何よりファイルサイズもタイムスタンプも異なります! JDK7の同名ファイルより古いですし。
そして、環境変数 JAVA_HOME の設定を戻して、JDK6を指すようにしてから、A/Commands の下を見てみると...

$ java -version
java version "1.6.0_31"
Java(TM) SE Runtime Environment (build 1.6.0_31-b04-415-11M3635)
Java HotSpot(TM) 64-Bit Server VM (build 20.6-b01-415, mixed mode)
$ which java
/usr/bin/java
$ ls -li /System/Library/Frameworks/JavaVM.framework/Versions/A/Commands
total 1280
...
40738311 -rwxr-xr-x  1 root  wheel  54272  4 15 20:59 java
...

全く変わっていないんですけど...。
ということは、これは推測なのですが /System/Library/Frameworks/JavaVM.framework/Versions/Commands 以下に入っているコマンドは全てプロキシで、呼び出されたら現在のデフォルトバージョンとして指定されているJavaのディレクトリにある同名のコマンドを呼ぶようになっているということでしょうか?
で、その呼び出し先を指定するのが Java Preferences.app の設定であり、環境変数 JAVA_HOME が設定されている場合はさらにそれを優先させる...と言った所ですかねえ。

以下のAppleの開発者向けドキュメントを読んでみたのですがイマイチ要領を得ません。
http://developer.apple.com/library/mac/#qa/qa1170/_index.html
http://developer.apple.com/library/mac/#documentation/Java/Conceptual/Java14Development/00-Intro/JavaDevelopment.html

どなたかこのあたりの事情に詳しい人いますか?

追伸

MacのJDK7にはJavaFX2.1のSDKが同梱されています。JDK7をデフォルトに設定すると、JavaFXアプリケーションのJARをFinderでダブルクリックするだけで起動できるようになります。
また、NetBean7.1.2をインストールすると、特別な設定なしでJavaFXの開発もできるようになります。