Mac Java の複雑な階層構成のまとめと管理

2008 年 11 月 16 日 | カテゴリー: プログラム, 環境構築

2008111601.png

元々の Mac OS X Leopard の特殊なディレクトリ階層に加えて、Sum Microsystems からは Mac 向け Java が提供されていないため Apple が Java を用意しているわけですが、これがさらに特殊な階層構成になっていました。

シンボリックリンクが多用されているうえに、どのタイミングでどのリンクを参照にしにいくのかを把握できなければ、どこを変更すればいいのかも分からないのですが、だいたい見えてきたので上記がそのまとめです。
# Visio で頑張ってビジュアライズしてみた。

Apple の Java パッケージについて

Java for Mac OS X 10.5 Update 2 には、JRE と JDK の両方が含まれており、しかも 1.3 から 1.6 までの全てがインストールされ、シンボリックリンクで切り替えられるような構成になっていました。
しかし、単純にひとつリンクを張り替えれば全て切り替わるわけではなくて、呼ばれるケースによって参照されるリンクが異なっているというやっかいな仕様なもよう;

/usr/bin/java や /usr/bin/javac のバージョンの切り替えについて

2008111602.png

/Applications/Utilities/Java Preferences.app で GUI からバージョンを切り替えるのが正解です。
Java SE 6 64-bit を選択すると以下なかんじに。

$ /usr/bin/java -version
java version "1.6.0_07"
Java(TM) SE Runtime Environment (build 1.6.0_07-b06-153)
Java HotSpot(TM) 64-bit Server VM (build 1.6.0_07-b06-57, mixed mode)

これでシンボリックリンクも切り替わっていれば、「これはリンクを張り替えるためのフロントエンドなんだ!」めでたしめでたし、となっていたのですが、そういうわけにはいかず。

$ ls -l /Systems/Library/Frameworks/JavaVM.framework/Versions
(一部省略)
lrwxr-xr-x 8 root wheel 272 2008-11-15 23:56 A
lrwxr-xr-x 8 root wheel   1 2008-11-15 23:56 Current -> A
lrwxr-xr-x 8 root wheel   3 2008-11-15 23:56 CurrentJDK > 1.5

/usr/bin/java は Current を参照しにいっているようです。

$ ls -l /usr/bin/java
lrwxr-xr-x 1 root wheel 74 2008-11-15 23:56 /usr/bin/java -> /System/Library/Frameworks/JavaVN.framework/Versions/Current/Commands/java

Current は A へのリンク。

$ ls -l /System/Library/Frameworks/JavaVN.framework/Versions/Current
lrwxr-xr-x 1 root wheel 74 2008-11-15 23:56 /System/Library/Frameworks/JavaVN.framework/Versions/Current -> A

さらに Commands/java は、A だと実体のように見えて、それ以外(1.5.0 や 1.6.0)だと ../Home/bin/java へのシンボリックリンク。

$ ls -l /System/Library/Frameworks/JavaVN.framework/Versions/Current/Commands/java
lrwxr-xr-x 1 root wheel 1 2008-11-15 09:06 /System/Library/Frameworks/JavaVN.framework/Versions/Current/Commands/java
$ ls -l /System/Library/Frameworks/JavaVN.framework/Versions/CurrentJDK/Commands/java
lrwxr-xr-x 1 root wheel 16 2008-11-15 23:56 /System/Library/Frameworks/JavaVN.framework/Versions/CurrentJDK/Commands/java -> ../Home/bin/java

A っていうのが何者なのかってことになるんですが、中身を見る限り、1.5 や 1.6 と同様 Java 本体のようです。
でもリンクじゃないのに切り替わるとはこれいかに?ハードリンクみたいな何かで、GUI で切り替わってる?いやでも Home が含まれてません。
それはおいといて、CurrentJDK が 1.5 のままで、この子は別の何かから参照される可能性があります。
これを切り替えるにはどうしましょうか(以下の JAVA_HOME についてで説明)。

CurrentJDK と JAVA_HOME について

Java Development Guide for Mac OS X: Overview of Java for Mac OS X

The Java Home Directory

Some applications look for Java’s home directory ($JAVA_HOME) on the user’s system, especially during installation. If you need to set this explicitly in a shell script or an installer, set it to /Library/Java/Home/. Setting it to the target of this symbolic link can result in a broken application for your customers down the road, when Apple ships a software update that changes the default version of Java, or when the user moves the application to another version of Mac OS X which has a different default version of Java. Programatically you can use System.getProperty(“java.home”), as you would expect.

/Library/Java/Home/ also contains the bin/ subdirectory where command-line tools like java and javac are found. These tools match the default version of Java for the system as defined by Apple. Additionally, the Java tools available on the default path in /usr/bin will dynamically target the top preferred version of Java that the user has chosen for applications in the Java Preferences application.

だいたいこのあたりを読んでみて、/Library/Java/Home を JAVA_HOME にしておくと幸せになれるらしいよという理解。
これもリンクなので辿ってみると、CurrentJDK/Home を指しているもよう。ということで、CurrentJDK のリンク先を 1.5 から 1.6 へ自分で切り替えておいて、JAVA_HOME を /Library/Java/Home にしておけばいいかんじ。

$ cd /Systems/Library/Frameworks/JavaVM.framework/Versions
$ sudo rm CurrentJDK
$ sudo ln -s 1.6 CurrentJDK

ちなみに Home を指しておけば $JAVA_HOME/bin で java, javac を参照して幸せなのはよしとして、Commands/java や Commands/javac は何者か ls -l で確認してみると、Home/bin 以下へのシンボリックリンクでした。

Java 関連ツールの管理場所 (/opt/java 以下に配置)

Windows であれば C:\Program Files\Java 以下。
Linux であれば /usr/local/java 以下。
jdk と同じ位置に ant や jruby を置くように管理していたのですが、Mac の jdk の位置と階層が特殊すぎて、同じにするのは気がひけます。

/usr/local 以下は Mac では最初は存在せず、Mercurial のパッケージが /usr/local 以下にバイナリを展開してきたり、中途半端に使われていたりで、ここに置くのも若干気持ち悪く。
MacPorts を /opt/ports (prefix 指定で名前は変更した) にインストールしたので、Java 関連も /opt/java 配下に置くようにすれば、同じように管理できていいかなと思い、合わせてみました。

$ ls -l
lrwxr-xr-x  1 root admin  16 2008-11-16 04:27 ant -> apache-ant-1.7.1
lrwxr-xr-x 14 root admin 476 2008-06-27 05:04 apache-ant-1.7.1
lrwxr-xr-x  1 root admin  10 2008-11-16 04:27 javacc -> javacc-4.0
lrwxr-xr-x  6 root admin 204 2008-11-03 07:51 javacc-4.0
lrwxr-xr-x  1 root admin  18 2008-11-16 04:11 jdk -> /Library/Java/Home
lrwxr-xr-x  1 root admin  11 2008-11-16 04:28 jruby -> jruby-1.1.5
lrwxr-xr-x 12 root admin 408 2008-11-03 16:46 jruby-1.1.5

環境変数を /etc/bashrc に設定

環境変数を /etc/bashrc に書いておこうかと思ったら、root でさえも書き込み権限がなかったので権限変更。
vim で末尾に追加編集します。

$ sudo chmod 644 /etc/bashrc
$ sudo vim /etc/bashrc
# for java
export JAVA_HOME=/opt/java/jdk
export ANT_HOME=/opt/java/ant
export JAVACC_HOME=/opt/java/javacc
export JRUBY_HOME=/opt/java/jruby

export PATH=$JAVA_HOME/bin:$ANT_HOME/bin:$JAVACC_HOME/bin:$JRUBY_HOME/bin:$PATH

$PATH の前に置いて優先的に読ませている理由は、XCode に含まれていた ant が /usr/share/ant なんていうところに展開されていたもので、消すのもなんなので優先順位だけ変えたということで。

bash 起動時に読み込んで欲しいので ~/.bashrc と ~/.bash_profile を作成します。
読み込む順番は ~/.bash_profile, ~/.bashrc, /etc/bashrc。

$ vim ~/.bashrc
# .bashrc

# User specific aliases and functions

# Source global definitions
if [ -f /etc/bashrc ]; then
    . /etc/bashrc
fi
$ vim ~/.bash_profile
# .bash_profile

# Get the aliases and functions
if [ -f ~/.bashrc ]; then
    . ~/.bashrc
fi

export PATH

ただしこれだと、ターミナルで bash を起動したときに有効になるだけで、GUI からアイコンをクリックして Java アプリケーションを起動、たとえば NetBeans なんかを起動したときには見てくれないそうです。
~/.MacOSX/environment.plist を作成して、GUI アプリケーション向け環境変数が書けるとかなんとか。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer/DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
    <dict>
        <key>JAVA_HOME</key>
        <string>/Library/Java/Home</string>
    </dict>
</plist>

他 OS での Java 環境構築例

Windows, Linux, FreeBSD, Mac の全ての Java 環境構築をコンプリートしてしまったわけですが、Mac が一番やっかいだったのは間違いないです。
BSD の diabolo を移植とかできないのかなあ。こんな構成になってるの Mac だけですし。

  1. c9katayama
    2008 年 12 月 17 日 11:11

    図が最高にわかりやすいです。ありがとうございます!

  2. 通りすがり
    2009 年 7 月 25 日 17:18

    図がわかりやすいです。

    >A っていうのが何者なのかってことになるんですが、中身を見る限り、1.5 や 1.6 と同様 Java 本体のようです。

    結局何者なんでしょうか・・