Ubuntuで、複数のJavaをインストールして切替を行う


- 複数のjavaをインストールして切替を行う方法について記載する。
- Ubuntu 16.04で実施。
- java8とjava9をインストールして切り替えてみる。

# やり方
## インストールするjavaの検索

```sh
$ sudo apt search openjdk-.*-jdk$

openjdk-8-jdk/xenial-updates,xenial-security 8u252-b09-1~16.04 amd64
  OpenJDK Development Kit (JDK)

openjdk-9-jdk/xenial 9~b114-0ubuntu1 amd64
  OpenJDK Development Kit (JDK)
```

## javaのインストール
### java8のインストール
```sh
$ sudo apt install openjdk-8-jdk
```
### java9のインストール
```sh
$ sudo apt install openjdk-9-jdk
```

## javaバージョンの確認
```sh
$ java -version
openjdk version "1.8.0_252"
OpenJDK Runtime Environment (build 1.8.0_252-8u252-b09-1~16.04-b09)
OpenJDK 64-Bit Server VM (build 25.252-b09, mixed mode)
```

## （切替の前に）update-alternativesについて
- /usr/bin配下のjavaはシンボリックリンクで、/etc/alternatives配下のjavaを指している。
- /etc/alternatives配下のjavaもシンボリックリンクで、下記の例だと、/usr/lib/jvm/java-8-openjdk-amd64/jre/binのjavaを指している。
- update-alternativesは、/etc/alternatives配下のシンボリックリンクを書き換えることで、バージョンの異なるjavaを指し示すことができる。（update-alternativesはjava以外にも利用可能）

```sh
$ which java
/usr/bin/java

$ ls -la /usr/bin/java
lrwxrwxrwx 1 root root 22 May  5 01:46 /usr/bin/java -> /etc/alternatives/java

$ ls -la /etc/alternatives/java
lrwxrwxrwx 1 root root 46 May  5 07:52 /etc/alternatives/java -> /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java
```

## javaの切替
試した手法を３つ記載しますが、手法３が個人的にはおすすめです。

### （手法１）update-alternativesで切り替える（※切替は中途半端）
- update-alternativesコマンドでインストールされているjavaが表示されるので、Selectionの番号を指定して切り替える。
- アスタリスクが付いているjavaが現在使用しているjava。
- 2を選択して、java9に切り替えてみる。

```sh
$ sudo update-alternatives --config java
There are 2 choices for the alternative java (providing /usr/bin/java).

  Selection    Path                                            Priority   Status
------------------------------------------------------------
  0            /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java   10        auto mode
* 1            /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java   10        manual mode
  2            /usr/lib/jvm/java-9-openjdk-amd64/bin/java       10        manual mode

Press <enter> to keep the current choice[*], or type selection number: 2
```

- 以下のようなメッセージが出た場合は、update-alternativesがjava8しか認識していないので、java9を登録してあげる必要がある。

```sh
$ sudo update-alternatives --config java
There is only one alternative in link group java (providing /usr/bin/java): /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java
Nothing to configure.
```

- 以下の登録コマンドを実行後、再度、切替を実施。（最後の数字はプライオリティ。）

```sh
sudo update-alternatives --verbose --install /usr/bin/java java /usr/lib/jvm/java-9-openjdk-amd64/jre/bin/java 10
```


- javaのバージョンが切り替わっていることが確認できる。

```sh
$ java -version
openjdk version "9-internal"
OpenJDK Runtime Environment (build 9-internal+0-2016-04-14-195246.buildd.src)
OpenJDK 64-Bit Server VM (build 9-internal+0-2016-04-14-195246.buildd.src, mixed mode)
``` 

- でも、/etc/alternativesのシンボリックリンクをみると、javaコマンドだけしか切り替わってないことがわかる。。。update-alternativesはjava専用のコマンドじゃないから、当たり前といえば当たり前。（実際には、/etc/alternativesにあるjava関連のコマンドはもっとたくさんある。）

```sh
$ ls -ltr /etc/alternatives/java*
lrwxrwxrwx 1 root root 45 May  5 08:03 /etc/alternatives/javadoc -> /usr/lib/jvm/java-8-openjdk-amd64/bin/javadoc
lrwxrwxrwx 1 root root 43 May  5 08:03 /etc/alternatives/javah -> /usr/lib/jvm/java-8-openjdk-amd64/bin/javah
lrwxrwxrwx 1 root root 43 May  5 08:03 /etc/alternatives/javac -> /usr/lib/jvm/java-8-openjdk-amd64/bin/javac
lrwxrwxrwx 1 root root 43 May  5 08:03 /etc/alternatives/javap -> /usr/lib/jvm/java-8-openjdk-amd64/bin/javap
lrwxrwxrwx 1 root root 42 May  5 08:04 /etc/alternatives/java -> /usr/lib/jvm/java-9-openjdk-amd64/bin/java
```

### （手法２）update-java-alternativesを使う（※切替は中途半端）
- java専用の切替コマンド、update-java-alternativesを使う。
- とは言いつつ、update-alternatives側にも各javaのバージョンを登録しておく必要がある。（update-java-alternatives内では、update-alternativesが使われているため。）
- jinfoに記載されているコマンドをupdate-alternativesにワンライナーで登録

```sh
$ cd /usr/lib/jvm
$ cat .java-1.9.0-openjdk-amd64.jinfo | grep -v -e '=' -e '^$' | awk '{system("sudo update-alternatives --verbose --install /usr/bin/" $2 " "$2 " " $3 " " 10)}'
```

- 切替ができるjavaを表示させてみる。

```sh
$ update-java-alternatives --list
java-1.8.0-openjdk-amd64       1081       /usr/lib/jvm/java-1.8.0-openjdk-amd64
java-1.9.0-openjdk-amd64       1091       /usr/lib/jvm/java-1.9.0-openjdk-amd64
```


- java9に切り替えてみる。

```sh
$ sudo update-java-alternatives --set java-1.9.0-openjdk-amd64
```

- 結局、update-java-alternativesでも全部切り替えてくれない。。。

```sh
$ ls -ltr /etc/alternatives/java*
lrwxrwxrwx 1 root root 45 May  5 08:03 /etc/alternatives/javadoc -> /usr/lib/jvm/java-8-openjdk-amd64/bin/javadoc
lrwxrwxrwx 1 root root 43 May  5 08:03 /etc/alternatives/javah -> /usr/lib/jvm/java-8-openjdk-amd64/bin/javah
lrwxrwxrwx 1 root root 43 May  5 08:03 /etc/alternatives/javac -> /usr/lib/jvm/java-8-openjdk-amd64/bin/javac
lrwxrwxrwx 1 root root 43 May  5 08:03 /etc/alternatives/javap -> /usr/lib/jvm/java-8-openjdk-amd64/bin/javap
lrwxrwxrwx 1 root root 42 May  5 08:24 /etc/alternatives/java -> /usr/lib/jvm/java-9-openjdk-amd64/bin/java
```


### (手法３)update-alternativesで切り替える -その２- （※おすすめ）
- 結局、update-alternativesを使ってjava関連のコマンドを全部切り替えるしかないか。。。
- update-alternativesへの登録はその２で実施した手順と同じ。

```sh
$ cd /usr/lib/jvm
$ cat .java-1.9.0-openjdk-amd64.jinfo | grep -v -e '=' -e '^$' | awk '{system("sudo update-alternatives --verbose --install /usr/bin/" $2 " "$2 " " $3 " " 10)}'
```

- update-alternativesでのjava関連コマンドをワンライナーで切替

```sh
$ cat .java-1.9.0-openjdk-amd64.jinfo | grep -v -e '=' -e '^$' | awk '{system("sudo update-alternatives --set " $2 " " $3 )}'
```

- java関連コマンドが全て切り替わっていることを確認。

```sh
$ ls -ltr /etc/alternatives/java*
lrwxrwxrwx 1 root root 42 May  5 08:24 /etc/alternatives/java -> /usr/lib/jvm/java-9-openjdk-amd64/bin/java
lrwxrwxrwx 1 root root 43 May  5 08:42 /etc/alternatives/javac -> /usr/lib/jvm/java-9-openjdk-amd64/bin/javac
lrwxrwxrwx 1 root root 43 May  5 08:42 /etc/alternatives/javah -> /usr/lib/jvm/java-9-openjdk-amd64/bin/javah
lrwxrwxrwx 1 root root 45 May  5 08:42 /etc/alternatives/javadoc -> /usr/lib/jvm/java-9-openjdk-amd64/bin/javadoc
lrwxrwxrwx 1 root root 43 May  5 08:42 /etc/alternatives/javap -> /usr/lib/jvm/java-9-openjdk-amd64/bin/javap
```

# 備考
- 上記のどの方法でも、JAVA_HOMEは切り替えてくれないので、個別に切り替える必要あり。
- jinfoに記載があるけど、実際に存在しないファイルもあるので、その場合は、`update-alternatives: error: alternative path /usr/lib/jvm/java-9-openjdk-amd64/bin/appletviewer doesn't exist`等といったエラーが発生するが、特に問題はなさそう。