gcjとjdkの使い分け

Javaはほとんど使ってないんだけどFedOneの影響で少しいじり始め。ちょっと調べてみたいことがあって、丁度手元にあったのでUbuntuでやってみようとする。
これまでLinuxJavaったことなかったんだけど、とりあえず出自も考えずにjavacしたら、なんか「Matcher.usePatternがねえ!」とか言われてからありゃりゃ?と。調べてみたらJDKじゃない、ということに気がついた。どうもgcjというネイティブコードに変換してくれるコンパイラらしく、eclipseとかtomcatとかで実績のあるすばらしいプロダクトらしいのだけれど、1.5までしか対応してないらしく、今回の遊びには不適切。「良くわからないけど、とりあえず入れなおそうかな」とremoveしてみたら、突然JDKが使えるようになってまたまたびっくりした。
どうもこれはLinuxのaltenativesとかいうもののシワザらしいぞ、と言うことに気がついて少し調べてみた。

alternatives機構

今回のjavacとかブラウザとかMTAのように、複数のインストール選択肢があるようなコマンド、または複数バージョンを共存させたい場合、もちろん名前で使い分けることは出来るんだけれど、いわゆる「デフォルトのなになに」を設定できると非常に便利。Linuxにはalternativesという機構があって、これが名前→実バイナリへの対応を管理してくれている。
仕組みは単純で、実行パス上にあるコマンドは実はシンボリックリンクになっていて、これが /etc/altenativesにあるデフォルト名のファイルを指し示している。で、これもシンボリックリンク(なんという迂遠!)になっていて、ここから正しいバイナリに飛ぶようになっている。

実際の設定

データベース自体は/var/lib/dpkg/alternativesにあり、ここにalternativesが管理する名前のファイルが入っている。各ファイルには対応する実バイナリの位置や優先度などが書き込まれていて、この情報を元にalternatives管理コマンドがシンボリックリンクを更新する仕組みになっている。
管理プログラムの名前は update-altenatives 。これに --display [名前] すると現在の状況を教えてくれる。たとえばjavaならこうなってた。

sawshark% update-alternatives --display java
java - auto mode
 リンクは現在 /usr/bin/gij-4.4 を指しています
/usr/bin/gij-4.4 - 優先度 1044
 スレーブ java.1.gz: /usr/share/man/man1/gij-4.4.1.gz
/usr/lib/jvm/java-6-sun/jre/bin/java - 優先度 63
 スレーブ java.1.gz: /usr/lib/jvm/java-6-sun/jre/man/man1/java.1.gz
現在の `最適' バージョンは /usr/bin/gij-4.4 です。
sawshark% update-alternatives --display javac
javac - auto mode
 リンクは現在 /usr/bin/gcj-wrapper-4.4 を指しています
/usr/bin/ecj - 優先度 143
 スレーブ javac.1.gz: /usr/share/man/man1/ecj.1.gz
/usr/bin/gcj-wrapper-4.4 - 優先度 1044
 スレーブ javac.1.gz: /usr/share/man/man1/gcj-wrapper-4.4.1.gz
/usr/lib/jvm/java-6-sun/bin/javac - 優先度 63
 スレーブ javac.1.gz: /usr/lib/jvm/java-6-sun/man/man1/javac.1.gz
現在の `最適' バージョンは /usr/bin/gcj-wrapper-4.4 です。
    • config java とかすると、候補が出てきて対話的に設定ができる。
sawshark% sudo update-alternatives --config java
There are 2 choices for the alternative java (providing /usr/bin/java).

  Selection    Path                                  Priority   Status
------------------------------------------------------------
* 0            /usr/bin/gij-4.4                       1044      auto mode
  1            /usr/bin/gij-4.4                       1044      manual mode
  2            /usr/lib/jvm/java-6-sun/jre/bin/java   63        manual mode

Press enter to keep the current choice[*], or type selection number: 2
update-alternatives: using /usr/lib/jvm/java-6-sun/jre/bin/java to provide /usr/bin/java (java) in manual mode.
sawshark% sudo update-alternatives --config javac
There are 3 choices for the alternative javac (providing /usr/bin/javac).

  Selection    Path                               Priority   Status
------------------------------------------------------------
* 0            /usr/bin/gcj-wrapper-4.4            1044      auto mode
  1            /usr/bin/ecj                        143       manual mode
  2            /usr/bin/gcj-wrapper-4.4            1044      manual mode
  3            /usr/lib/jvm/java-6-sun/bin/javac   63        manual mode

Press enter to keep the current choice[*], or type selection number: 3
update-alternatives: using /usr/lib/jvm/java-6-sun/bin/javac to provide /usr/bin/javac (javac) in manual mode.

これで

sawshark% java -version
java version "1.6.0_15"
Java(TM) SE Runtime Environment (build 1.6.0_15-b03)
Java HotSpot(TM) 64-Bit Server VM (build 14.1-b02, mixed mode)
sawshark% javac -version
javac 1.6.0_15

とかなっているよう。auto mode とか良くわかんないので後で調べる。

わからない点

  • auto modeとかなによ?
  • システムワイドのみ? ユーザローカルなのないの?
  • スレーブ? 便利そう(コンパイラ& VM同時に変更できる)。めんどくさそう。

とか。