JavaユーザーのためのパッケージマネージャーSDKMAN

【追記】2021.09.01
記事を書いて５年ほど放置していましたが、この記事を書いたあとにsdkman自体もどんどんアップデートされていき使いやすくなっていきました。
特に、記事執筆時点ではsdkman本体とは別に自身でJDKをインストールする必要があったのがなんとJDKの選択、導入自体もsdkman上から行えるようになっています。
Groovy周りから発展したツールというのを飛び抜けて、Javaユーザー全般が使うツールとなってきたのでいくつか追記しました。

# 概要
Groovyでは今までパッケージマネージャーとしてGVMというツールが使われてきました。
これはRubyで言うRVMやrbenvのようなもので(といっても私はRuby使っていないので詳しくないですが)Groovyの環境を導入したりバージョンを管理できたりするツールです。
またGradleやGrailsなどGroovy系のツールの管理もできます。
同一ツールの複数バージョンをインストールできコマンド一つで切り替えたりが簡単にできます。

しかしGVMという名称はGo言語のパッケージマネージャーとかぶる名前で共存できませんでした。
そのためどうかはわかりませんが、最近ツール名が変わってSDKMANという名前になりました。
http://sdkman.io/

最初は名前が変わった程度で深く考えていなかったのですが、最近とある情報からSpring Bootも導入できると聞いて改めてリストを確認したところ、Groovyに限らずJVM系ツールがかなり追加されていました。
SDKMAN(おそらくSDK Managerの略)の名前通り色々と導入・管理できそうです。
そこでこれをGroovyユーザーしか知らないのはもったいないと思うので紹介します。

# ツール一覧

2021.09.01現在では次のようなツールを導入することができます。
記事執筆時点と比較してJava関連のツールやフレームワークの対応がかなり増えています。

* Apache ActiveMQ
* Ant
* AsciidoctorJ
* Ballerina
* Bpipe
* BTrace
* Concurnas
* ConnOR
* CUBA CLI
* CXF
* docToolchain
* Flink
* Gaiden
* Gradle
* Gradle profiler
* Grails
* Groovy
* GroovyServ
* hadoop
* http4k
* Infrastructor
* Java
* JBake
* J'Bang
* JDK Mission Control
* Apache JMeter
* JReleaser
* Karaf
* Kotlin
* kscript
* Layrry
* Leiningen
* Maven
* Micronaut
* Mule Flow Diagrams
* Maven Daemon
* Pomchecker
* Quarkus CLI
* sbt
* Scala
* Spark
* Spring Boot
* Sshoogr
* Apache Tomcat
* Vert.x
* VisualVM
* Webtau
* Znai

初版投稿時点(2015/10/30)では次のような感じでした。
まだGVMから移行してすぐだったので基本的にGroovy関連のプロダクトが多く、現在ではメンテされてなくて消えているものもいくつかありますね。

* AsciidoctorJ
* CRaSH
* Gaiden
* Glide
* Gradle
* Grails
* Grails
* Griffon
* Groovy
* GroovyServ
* JBake
* JBoss Forge
* Lazybones
* Maven
* sbt
* Scala
* Spring Boot
* Vert.X

# 動作環境
公式サイトによると下記環境で動作するようです。

* Linux
* Mac
* Cygwin
* ~~Power Shell~~
* **WSL**
* ~~Unix~~
    * **Soralis**
    * **FreeBSD**

2021.09.01現在ではPowerShellのサポートが外れて代わりにWSLが入っているようです。また従来Unixと記載されていたところがSoralis、FreeBSDと別れて記述されてました。
基本的にUnix系OSだけのサポートになったって感じですかね。

~~私はWindowsユーザーなのでCygwinで使っています。
その他、Java周辺ツールなのでJavaは予め導入しておかなければいけません。
逆にいえばJavaさえ入っていれば問題ありません。~~

現在はWindows環境ではWSLを使用しています。
最近ではIntelliJ IDEA上で選択できるJDKにWSL側のJavaを指定できるようになったので、Windowsネイティブな対応がなくても問題は少なくなってきました。
また先にも述べたとおりJava自体もsdkmanで導入できるので面倒が減りました。

# 導入方法
上記環境を満たしている場合下記のコマンドをシェルで実行するだけで導入が完了します。

```bash
curl -s get.sdkman.io | bash
```

インストールが完了すると、一旦シェルを閉じて新規シェルを起動すると（もしくは.bashrc、.zshrcのリロードで）使いはじめることができます。
コマンド名は`sdk`です。
試しに下記コマンドを打つと現在のバージョンが確認できます。

```bash
sdk version
```

(個人的にはコマンド名がsdkとか言うなんのコマンドなのかよくわからないのはどうなのかと思いつつ)

# 使い方
導入できるツール一覧は下記のコマンドで確認できます。

```bash
sdk list
```

## Javaインストール

Javaがインストールできるようになったのでこちらの説明を追記します。
まずはインストールできるJavaのバージョンを確認してみます。

```
sdk list java
```

とコマンドを打つと下記のように一覧が表示されます。

```
================================================================================
Available Java Versions
================================================================================
 Vendor        | Use | Version      | Dist    | Status     | Identifier
--------------------------------------------------------------------------------
 AdoptOpenJDK  |     | 16.0.1.j9    | adpt    |            | 16.0.1.j9-adpt
               |     | 16.0.1.hs    | adpt    |            | 16.0.1.hs-adpt
               |     | 11.0.11.j9   | adpt    |            | 11.0.11.j9-adpt
               | >>> | 11.0.11.hs   | adpt    | installed  | 11.0.11.hs-adpt
               |     | 8.0.292.j9   | adpt    |            | 8.0.292.j9-adpt
               |     | 8.0.292.hs   | adpt    |            | 8.0.292.hs-adpt
 Corretto      |     | 16.0.2.7.1   | amzn    |            | 16.0.2.7.1-amzn
               |     | 11.0.12.7.1  | amzn    |            | 11.0.12.7.1-amzn
               |     | 8.302.08.1   | amzn    |            | 8.302.08.1-amzn
 Dragonwell    |     | 11.0.9.4     | albba   |            | 11.0.9.4-albba
               |     | 8.5.5        | albba   |            | 8.5.5-albba
 GraalVM       |     | 21.2.0.r16   | grl     |            | 21.2.0.r16-grl
               |     | 21.2.0.r11   | grl     |            | 21.2.0.r11-grl
               |     | 21.2.0.r8    | grl     |            | 21.2.0.r8-grl
               |     | 21.1.0.r8    | grl     |            | 21.1.0.r8-grl
               |     | 20.3.3.r11   | grl     |            | 20.3.3.r11-grl
               |     | 20.3.3.r8    | grl     |            | 20.3.3.r8-grl
               |     | 20.3.2.r8    | grl     |            | 20.3.2.r8-grl
               |     | 19.3.6.r11   | grl     |            | 19.3.6.r11-grl
               |     | 19.3.6.r8    | grl     |            | 19.3.6.r8-grl
 Java.net      |     | 18.ea.12     | open    |            | 18.ea.12-open
               |     | 18.ea.11     | open    |            | 18.ea.11-open
               |     | 18.ea.10     | open    |            | 18.ea.10-open
               |     | 18.ea.2.lm   | open    |            | 18.ea.2.lm-open
               |     | 17.ea.3.pma  | open    |            | 17.ea.3.pma-open
               |     | 16.0.2       | open    |            | 16.0.2-open
               |     | 11.0.12      | open    |            | 11.0.12-open
               |     | 11.0.11      | open    |            | 11.0.11-open
               |     | 11.0.10      | open    |            | 11.0.10-open
               |     | 11.0.2       | open    |            | 11.0.2-open
               |     | 8.0.302      | open    |            | 8.0.302-open
               |     | 8.0.292      | open    |            | 8.0.292-open
               |     | 8.0.282      | open    |            | 8.0.282-open
               |     | 8.0.265      | open    |            | 8.0.265-open
 Liberica      |     | 16.0.2.fx    | librca  |            | 16.0.2.fx-librca
               |     | 16.0.2       | librca  |            | 16.0.2-librca
               |     | 11.0.12.fx   | librca  |            | 11.0.12.fx-librca
               |     | 11.0.12      | librca  |            | 11.0.12-librca
               |     | 8.0.302.fx   | librca  |            | 8.0.302.fx-librca
               |     | 8.0.302      | librca  |            | 8.0.302-librca
 Liberica NIK  |     | 21.2         | nik     |            | 21.2-nik
               |     | 21.1         | nik     |            | 21.1-nik
               |     | 21.0.0.2     | nik     |            | 21.0.0.2-nik
 Mandrel       |     | 21.2.0.0     | mandrel |            | 21.2.0.0-mandrel
               |     | 20.3.3.0     | mandrel |            | 20.3.3.0-mandrel
 Microsoft     |     | 16.0.2.7.1   | ms      |            | 16.0.2.7.1-ms
               |     | 11.0.12.7.1  | ms      |            | 11.0.12.7.1-ms
 SapMachine    |     | 16.0.2       | sapmchn |            | 16.0.2-sapmchn
               |     | 11.0.12      | sapmchn |            | 11.0.12-sapmchn
 Semeru        |     | 16.0.2       | sem     |            | 16.0.2-sem
               |     | 11.0.12      | sem     |            | 11.0.12-sem
               |     | 8.0.302      | sem     |            | 8.0.302-sem
 Temurin       |     | 16.0.2       | tem     |            | 16.0.2-tem
               |     | 11.0.12      | tem     |            | 11.0.12-tem
               |     | 8.0.302      | tem     |            | 8.0.302-tem
 Trava         |     | 11.0.9       | trava   |            | 11.0.9-trava
               |     | 8.0.232      | trava   |            | 8.0.232-trava
 Zulu          |     | 16.0.2       | zulu    |            | 16.0.2-zulu
               |     | 16.0.2.fx    | zulu    |            | 16.0.2.fx-zulu
               |     | 11.0.12      | zulu    |            | 11.0.12-zulu
               |     | 11.0.12.fx   | zulu    |            | 11.0.12.fx-zulu
               |     | 8.0.302      | zulu    |            | 8.0.302-zulu
               |     | 8.0.302.fx   | zulu    |            | 8.0.302.fx-zulu
               |     | 7.0.312      | zulu    |            | 7.0.312-zulu
               |     | 6.0.119      | zulu    |            | 6.0.119-zulu
================================================================================
Use the Identifier for installation:

    $ sdk install java 11.0.3.hs-adpt
================================================================================
```

かなり多くの種類がありますね。（自分の環境ではAdopt 11.0.11.hsをすでに導入済みなのでそこのステータスが選択されいますね）
ご存知のように最近のJavaでは従来のOracleJDK、OpenJDKだけではなく各ベンダーがJDKをリリースしています。
メジャーどころではAdopt、Zulu、Microsoft等
各ベンダーそれぞれ導入することができます。
インストール方法はコマンドの出力の最下部に書かれている通り`sdk install java`コマンドを使用します。
バージョンを指定しない場合Adoptの現在のLTS(11)のHotSpotバージョンが選択されるようです。

```
sdk install java 16.0.2-zulu
```

といった感じで特定のバージョンを指定してあげればそれをインストールすることもできます。
（ちなみにコマンド出力の例では11.0.3が指定されているのですが、実際に入力するとエラーが出ます。どうもマイナーバージョンが上がると古いものは削除されるようで、最新メジャーバージョンかLTSでないと選択できないようです）

```
Downloading: java 16.0.2-zulu

In progress...

################################################################################################################# 100.0%

Repackaging Java 16.0.2-zulu...

Done repackaging...

Installing: java 16.0.2-zulu
Done installing!

Do you want java 16.0.2-zulu to be set as default? (Y/n):

Setting java 16.0.2-zulu as default.
```

といった感じでインストールが進み最後に導入したものをデフォルトにするかと聞かれます。
環境に初めてJDKを入れるのであればデフォルトで問題ないと思います。デフォルトにするとShellから`java`コマンドが使用できるようになります。

ベンダーやバージョンを変えて複数のJDKを導入することも可能です。
例えば

```
sdk install java 11.0.11.hs-adpt
sdk install java 16.0.2-zulu
```

として複数導入、デフォルトは11.0.11.hs-adptにしたとします。（つまり2番めのインストールのときの選択肢をNoにする）
Javaバージョンを確認するときちんとAdoptの11が表示されますね。

```
java --version

> openjdk 11.0.11 2021-04-20
> OpenJDK Runtime Environment AdoptOpenJDK-11.0.11+9 (build 11.0.11+9)
> OpenJDK 64-Bit Server VM AdoptOpenJDK-11.0.11+9 (build 11.0.11+9, mixed mode)
```

その後使用するJDKを変えたい時は`sdk default`コマンドを使用します。

```
sdk default java 16.0.2-zulu

> Default java version set to 11.0.11.hs-adpt
```

もう一度バージョンを確認してみましょう

```
java--version

> openjdk 16.0.2 2021-07-20
> OpenJDK Runtime Environment Zulu16.32+15-CA (build 16.0.2+7)
> OpenJDK 64-Bit Server VM Zulu16.32+15-CA (build 16.0.2+7, mixed mode, sharing)
```

簡単に切り替えることができました。

## その他ツールの導入

Javaの導入ができたら他のツールも同様に`sdk list {ツール名}`でバージョンを確認して`sdk install {ツール名} {バージョン}`で導入することができます。
下記の記述は初版投稿時点での説明のため追記した上述のJava導入と説明がかぶっていますが、そのまま載せておきます。

例えばSpring Bootを導入したい場合は次のコマンドを実行します。

```bash
sdk install springboot
```

ダウンロードが始まり、インストールが完了するとこのバージョンをデフォルトにするか聞かれるのでそのままエンターすれば導入が完了します。
インストールコマンド実行時にバージョン指定すると特定のバージョンを導入できます。
省略した場合は最新のリリースバージョンです。
導入できるバージョンを確認するためには次のように入力します。

```bash
sdk list springboot
```

かきのように一覧が出てきます。

```
     1.3.0.RC1            1.1.8.RELEASE
     1.3.0.M5             1.1.7.RELEASE
     1.3.0.M4             1.1.6.RELEASE
     1.3.0.M3             1.1.5.RELEASE
     1.3.0.M2             1.1.4.RELEASE
     1.3.0.M1             1.1.3.RELEASE
     1.2.7.RELEASE        1.1.2.RELEASE
     1.2.6.RELEASE        1.1.12.RELEASE
     1.2.5.RELEASE        1.1.11.RELEASE
     1.2.4.RELEASE        1.1.10.RELEASE
     1.2.3.RELEASE        1.1.1.RELEASE
     1.2.2.RELEASE        1.1.0.RELEASE
     1.2.1.RELEASE        1.0.2.RELEASE
     1.2.0.RELEASE        1.0.1.RELEASE
     1.1.9.RELEASE        1.0.0.RELEASE
```

例えばSpring Boot 1.3.0.RC1を入れたい場合

```bash
sdk install springboot 1.3.0.RC1
```

と実行することでインストールできます。
デフォルトで使用するバージョンを変更する場合

```bash
sdk default springboot 1.3.0.RC1
```

などのようにコマンドを実行すればよいです。

インストールされたバージョンの確認もlistコマンドを実行することでわかります。

```bash
{ ~ }  » sdk list springboot

================================================================================
Available Springboot Versions
================================================================================
 > * 1.3.0.RC1            1.1.8.RELEASE
     1.3.0.M5             1.1.7.RELEASE
     1.3.0.M4             1.1.6.RELEASE
     1.3.0.M3             1.1.5.RELEASE
     1.3.0.M2             1.1.4.RELEASE
     1.3.0.M1             1.1.3.RELEASE
   * 1.2.7.RELEASE        1.1.2.RELEASE
     1.2.6.RELEASE        1.1.12.RELEASE
     1.2.5.RELEASE        1.1.11.RELEASE
     1.2.4.RELEASE        1.1.10.RELEASE
     1.2.3.RELEASE        1.1.1.RELEASE
     1.2.2.RELEASE        1.1.0.RELEASE
     1.2.1.RELEASE        1.0.2.RELEASE
     1.2.0.RELEASE        1.0.1.RELEASE
     1.1.9.RELEASE        1.0.0.RELEASE

================================================================================
+ - local version
* - installed
> - currently in use
================================================================================

```

バージョンの左にローカルにインストールされているものは*で、デフォルトは>がついています。

# 終わりに
このようにSDKMAN自体のインストールもコマンド一発、ツールのインストール、切り替えもコマンド一発でできることがわかります。
~~このくらいツールが揃っていればGroovyユーザーでなくても導入する価値はあるのではないでしょうか？~~
SDKMANに名前が変わってからももうとても時間が経ち、ツールとしてかなり成熟してきておりJavaエンジニアでもかなりメジャーなものになったかなと思っています。
JDKのバージョン管理だけでもとても優秀なので、まだ導入されていない方は是非使ってみてはどうでしょうか？