2016/07/31

update-java-alternatives に Oracle java も追加する

@[Ubuntu](http://www.ubuntu.com/) 16.04 LTS

2016/8/4 追記
最新の update-java-alternatives は javac 等を更新してくれないバグがあります。 一時的なものだと思われますが、ご注意ください。

[穀風: 最新版の update-java-alternatives は javac を更新してくれない](https://kokufu.blogspot.jp/2016/08/update-java-alternatives-javac.html)
`update-java-alternatives` には `--install` のようなコマンドがないため、簡単に対象を追加することは出来ません一般的にはパッケージから入れた時に自動的に追加される。 ただ、その中身は単なる `update-alternatives`-java- がついていない のラッパースクリプトなので、動作を理解すれば、任意の JDK (JRE) を手動で登録して、切り替えられるようにすることが可能です。 今回は [Oracle](http://www.oracle.com/technetwork/java/javase/downloads/index.html) から jdk-8u101 をダウンロードして追加してみました。 ### update-alternatives とは `update-alternatives` について少しだけ書いておきたいと思います。 `update-alternatives` は複数バージョンあるコマンドを簡単に切り替えるためのツールです。 例えば、以下のように `/usr/bin/java` を切り替えることが出来ます既に 古い Oracle java を追加してある。 ```console `gutter: false; $ update-alternatives --config java There are 2 choices for the alternative java (providing /usr/bin/java). Selection Path Priority Status ------------------------------------------------------------ 0 /usr/lib/jvm/jdk-1.8.0_91-oracle/jre/bin/java 1081 auto mode 1 /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java 1081 manual mode * 2 /usr/lib/jvm/jdk-1.8.0_91-oracle/jre/bin/java 1081 manual mode Press to keep the current choice[*], or type selection number: ``` `update-alternatives` 自体は java とは関係がなく、任意のコマンドを切り替え可能なツールです。 > 参考 > [update-alternativesに管理してもらうコマンドを追加する。 - Qiita](http://qiita.com/hidekuro/items/f931ae527244bce34698) ### update-java-alternatives を使う理由 バージョン違いの java を切り替えるだけなら、 `update-alternatives` で十分な気がします。 ところが、java の動作環境を正しく変更するには、`java`, `javac`, `jar`...etc と膨大な数といっても 40個くらいですがのコマンドを切り替えなければなりません。 これらを一気に処理してしまおうというのが、`update-java-alternatives` です。 具体的には `/usr/lib/jvm/.*.jinfo` ファイルの情報を基に `update-alternatives` を実行するシェルスクリプトになっています。 つまり、`/usr/lib/jvm/.*.jinfo` ファイルを新規作成すれば `update-java-alternatives` に新たな項目を追加出来るわけです実際はもうひと手間かかる。後述。。 以下が実際の `/usr/lib/jvm/.java-1.8.0-openjdk-amd64.jinfo` です。 後半の各項目が `update-alternatives` で切り替えられます。 ``` name=java-8-openjdk-amd64 alias=java-1.8.0-openjdk-amd64 priority=1081 section=main hl rmid /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/rmid hl java /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java hl keytool /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/keytool hl jjs /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/jjs hl pack200 /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/pack200 hl rmiregistry /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/rmiregistry hl unpack200 /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/unpack200 hl orbd /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/orbd hl servertool /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/servertool hl tnameserv /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/tnameserv hl jexec /usr/lib/jvm/java-8-openjdk-amd64/jre/lib/jexec jre policytool /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/policytool jdkhl idlj /usr/lib/jvm/java-8-openjdk-amd64/bin/idlj jdkhl jdeps /usr/lib/jvm/java-8-openjdk-amd64/bin/jdeps jdkhl wsimport /usr/lib/jvm/java-8-openjdk-amd64/bin/wsimport jdkhl rmic /usr/lib/jvm/java-8-openjdk-amd64/bin/rmic jdkhl jinfo /usr/lib/jvm/java-8-openjdk-amd64/bin/jinfo jdkhl jsadebugd /usr/lib/jvm/java-8-openjdk-amd64/bin/jsadebugd jdkhl native2ascii /usr/lib/jvm/java-8-openjdk-amd64/bin/native2ascii jdkhl jstat /usr/lib/jvm/java-8-openjdk-amd64/bin/jstat jdkhl javac /usr/lib/jvm/java-8-openjdk-amd64/bin/javac jdkhl javah /usr/lib/jvm/java-8-openjdk-amd64/bin/javah jdkhl jstack /usr/lib/jvm/java-8-openjdk-amd64/bin/jstack jdkhl jrunscript /usr/lib/jvm/java-8-openjdk-amd64/bin/jrunscript jdkhl javadoc /usr/lib/jvm/java-8-openjdk-amd64/bin/javadoc jdkhl javap /usr/lib/jvm/java-8-openjdk-amd64/bin/javap jdkhl jar /usr/lib/jvm/java-8-openjdk-amd64/bin/jar jdkhl extcheck /usr/lib/jvm/java-8-openjdk-amd64/bin/extcheck jdkhl schemagen /usr/lib/jvm/java-8-openjdk-amd64/bin/schemagen jdkhl jps /usr/lib/jvm/java-8-openjdk-amd64/bin/jps jdkhl xjc /usr/lib/jvm/java-8-openjdk-amd64/bin/xjc jdkhl jarsigner /usr/lib/jvm/java-8-openjdk-amd64/bin/jarsigner jdkhl jmap /usr/lib/jvm/java-8-openjdk-amd64/bin/jmap jdkhl jstatd /usr/lib/jvm/java-8-openjdk-amd64/bin/jstatd jdkhl jhat /usr/lib/jvm/java-8-openjdk-amd64/bin/jhat jdkhl jdb /usr/lib/jvm/java-8-openjdk-amd64/bin/jdb jdkhl serialver /usr/lib/jvm/java-8-openjdk-amd64/bin/serialver jdkhl wsgen /usr/lib/jvm/java-8-openjdk-amd64/bin/wsgen jdkhl jcmd /usr/lib/jvm/java-8-openjdk-amd64/bin/jcmd jdk appletviewer /usr/lib/jvm/java-8-openjdk-amd64/bin/appletviewer jdk jconsole /usr/lib/jvm/java-8-openjdk-amd64/bin/jconsole ``` ### Oracle java を update-java-alternatives で使えるようにする 実際の手順として、Oracle java をインストールして、切り替え可能にしてみます。 まず、[Java SE - Downloads](http://www.oracle.com/technetwork/java/javase/downloads/index.html) より必要な jdk (jre) をダウンロードし、`/usr/lib/jvm` 以下に展開します。 ここでは、`jdk-8u101-linux-x64.tar.gz` をダウンロードし、`jdk-1.8.0_101-oracle` に展開したものとします。 次に、`.*.jinfo` を作成します。 一から作成すると大変なので、既存のものをコピーし、一部を置換するのが良いでしょう。 以下のように `sed` を使って置換と同時にコピーを生成すると楽です。 ```console `gutter: false; $ cd /usr/lib/jvm $ sed -e "s/\(java-8-openjdk-amd64\|java-1.8.0-openjdk-amd64\)/jdk-1.8.0_101-oracle/g" .java-1.8.0-openjdk-amd64.jinfo | sudo tee .jdk-1.8.0_101-oracle.jinfo ``` `update-java-alternatives --list` を実行して認識されていれば成功です。 ```console `gutter: false; $ update-java-alternatives --list java-1.8.0-openjdk-amd64 1081 /usr/lib/jvm/java-1.8.0-openjdk-amd64 jdk-1.8.0_101-oracle 1081 /usr/lib/jvm/jdk-1.8.0_101-oracle ``` ### update-alternatives に登録する 「以上で終了」だと良いのですが、残念ながら、もうひと手間かかります。 この状態で `--set` を実行するとそんなコマンドは登録されていない旨のエラーが出てしまうのです。 ```console `gutter: false; $ sudo update-java-alternatives --set jdk-1.8.0_101-oracle update-alternatives: error: no alternatives for mozilla-javaplugin.so update-alternatives: error: alternative /usr/lib/jvm/jdk-1.8.0_101-oracle/jre/bin/java for java not registered; not setting update-alternatives: error: alternative /usr/lib/jvm/jdk-1.8.0_101-oracle/jre/lib/jexec for jexec not registered; not setting update-alternatives: error: alternative /usr/lib/jvm/jdk-1.8.0_101-oracle/jre/bin/jjs for jjs not registered; not setting update-alternatives: error: alternative /usr/lib/jvm/jdk-1.8.0_101-oracle/jre/bin/keytool for keytool not registered; not setting update-alternatives: error: alternative /usr/lib/jvm/jdk-1.8.0_101-oracle/jre/bin/orbd for orbd not registered; not setting update-alternatives: error: alternative /usr/lib/jvm/jdk-1.8.0_101-oracle/jre/bin/pack200 for pack200 not registered; not setting update-alternatives: error: alternative /usr/lib/jvm/jdk-1.8.0_101-oracle/jre/bin/rmid for rmid not registered; not setting update-alternatives: error: alternative /usr/lib/jvm/jdk-1.8.0_101-oracle/jre/bin/rmiregistry for rmiregistry not registered; not setting update-alternatives: error: alternative /usr/lib/jvm/jdk-1.8.0_101-oracle/jre/bin/servertool for servertool not registered; not setting update-alternatives: error: alternative /usr/lib/jvm/jdk-1.8.0_101-oracle/jre/bin/tnameserv for tnameserv not registered; not setting update-alternatives: error: alternative /usr/lib/jvm/jdk-1.8.0_101-oracle/jre/bin/unpack200 for unpack200 not registered; not setting update-alternatives: error: alternative /usr/lib/jvm/jdk-1.8.0_101-oracle/bin/appletviewer for appletviewer not registered; not setting update-alternatives: error: alternative /usr/lib/jvm/jdk-1.8.0_101-oracle/bin/jconsole for jconsole not registered; not setting update-alternatives: error: alternative /usr/lib/jvm/jdk-1.8.0_101-oracle/jre/bin/policytool for policytool not registered; not setting ``` 先にも述べたように、`update-java-alternatives` は単なるラッパーなので、大元の `update-alternatives` に登録されていなければいけません。 これらの項目を全て手作業で登録するのは現実的ではありませんので、 以下のように `.jdk-1.8.0_101-oracle.jinfo` の情報を基に、各項目に対して `update-alternatives --install` を実行すると良いでしょうこの機能を `update-java-alternatives` が持ってたら良かったのだけど。 ```console `gutter: false; cat .jdk-1.8.0_101-oracle.jinfo | awk -F'[ =]' '/^priority/ { priority=$2 } /^(hl|jre|jdk)/ { print "/usr/bin/" $2 " " $2 " " $3 " " priority; "\n" }' | xargs -t -n4 sudo update-alternatives --verbose --install ``` > 参考 > [Linuxで複数バージョンのJavaを管理する - Yahoo!知恵袋](http://note.chiebukuro.yahoo.co.jp/detail/n275457) ### update-java-alternatives で切り替える 実際に使用する際は、 `--list` で一覧を表示 ```console `gutter: false; $ update-java-alternatives --list java-1.8.0-openjdk-amd64 1081 /usr/lib/jvm/java-1.8.0-openjdk-amd64 jdk-1.8.0_101-oracle 1081 /usr/lib/jvm/jdk-1.8.0_101-oracle ``` `--set` で切り替えます ```console `gutter: false; $ sudo update-java-alternatives --set jdk-1.8.0_101-oracle $ java -version java version "1.8.0_101" Java(TM) SE Runtime Environment (build 1.8.0_101-b13) Java HotSpot(TM) 64-Bit Server VM (build 25.101-b13, mixed mode) ``` ### 環境変数 JAVA_HOME, JDK_HOME を設定 環境変数 `JAVA_HOME` や `JDK_HOME` を使うアプリケーションもあるため、これらも適切に変更しておく必要があります。 `update-java-alternatives` にそういった機能があれば良いのですが、残念ながら無いので、`~/.profile` 等に以下の項目を加えます。 ```shell JAVA_DIR=`readlink -f /usr/bin/java` if [ -x $JAVA_DIR ]; then export JAVA_HOME=$(echo ${JAVA_DIR} | sed "s:/bin/java::") export JDK_HOME=$JAVA_HOME fi ``` `update-java-alternatives --set` を実行したら `~/.profile` を再読みこみしましょう。 ```console `gutter: false; $ sudo update-java-alternatives --set jdk-1.8.0_101-oracle $ source ~/.profile ``` 以上で Oracle java を `update-java-alternatives` で切り替えられるようになりました。 ### [参考] update-java-alternatives から削除する 削除したい場合は、以下のように `update-alternatives --remove` で個々のエントリーを削除した後、`.*.jinfo` ファイルを削除します。 ```console `gutter: false; $ cat .jdk-1.8.0_91-oracle.jinfo | awk -F'[ =]' '/^priority/ { priority=$2 } /^(hl|jre|jdk)/ { print $2 " " $3; "\n" }' | xargs -t -n2 sudo update-alternatives --verbose --remove $ sudo rm .jdk-1.8.0_91-oracle.jinfo ``` ### [参考] 実際のシンボリックリンク 実際のシンボリックリンクは `/etc/alternatives/` 以下に一度張られ、その先を都度書き換えるという形で実現されています。 ```console `gutter: false; $ ls -l /usr/bin/java lrwxrwxrwx 1 root root 22 7月 31 13:09 /usr/bin/java -> /etc/alternatives/java* $ ls -l /etc/alternatives/java lrwxrwxrwx 1 root root 46 7月 31 18:07 /etc/alternatives/java -> /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java* ```

0 件のコメント: