jEnvのセットアップ&操作方法(Mac)

## 「jEnv」とは？

Javaの環境管理ツールです。jEnvを導入することにより、簡単にJavaのバージョンを切り替えて使うことができるようになります。
Pythonでいうpyenvです。操作方法もほぼ同様です。

## 環境

- OS：macOS Big Sur 11.1
- Homebrew：3.0.11
- jEnv：0.5.4

## セットアップ

### jEnvのインストール

Homebrewからインストールします。

```bash
$ brew update
$ brew install jenv
```

`.bash_profile` に以下を追記し、パスを通します。

```diff_shell:.bash_profile
+ # jEnv
+ export JENV_ROOT="$HOME/.jenv"
+ if [ -d "${JENV_ROOT}" ]; then
+   export PATH="$JENV_ROOT/bin:$PATH"
+   eval "$(jenv init -)"
+ fi
```

### jenvのインストール確認

`jenv doctor` コマンドを実行し、jEnvのインストールに問題ないか確認します。

私の場合、エラーが3つ出力されました。

```shell-session
$ jenv doctor
[ERROR] JAVA_HOME variable already set, scripts that use it directly could not use java version set by jenv
[ERROR] Java binary in path is not in the jenv shims.
[ERROR] Please check your path, or try using /path/to/java/home is not a valid path to java installation.
        PATH : {PATH}
```

すでに `JAVA_HOME` 環境変数に値がセットされているためにエラーが発生しています。

私は `.bash_profile` で `JAVA_HOME` をセットしているのが原因でした。

```bash:.bash_profile
# Androidアプリ開発
export JAVA_HOME=/Applications/Android\ Studio.app/Contents/jre/jdk/Contents/Home
if [ -d "${JAVA_HOME}" ]; then
  export PATH="${JAVA_HOME}/bin:$PATH"
fi
```

上記の処理を削除して `source ~/.bash_profile` を実行すると、エラーが解消されました。

```shell-session
$ jenv doctor
[OK]    No JAVA_HOME set
[OK]    Java binaries in path are jenv shims
[OK]    Jenv is correctly loaded
```

Androidアプリ開発で `adb` コマンドを使うときなどに問題が発生する可能性があるため、Androidアプリ開発する際は `jenv local openjdk64-1.8.0.242-release` のようにAndroid Studio内のJVM Homeを使うようにするのがいいと思います。

### JAVA_HOMEのセット

デフォルトでは `JAVA_HOME` 環境変数に何もセットされません。

```shell-session
$ echo $JAVA_HOME

```

`export` プラグインを有効にすることで `JAVA_HOME` に自動的に値がセットされます。

```shell-session
$ jenv enable-plugin export
You may restart your session to activate jenv export plugin echo export plugin activated

 echo $JAVA_HOME
/Users/{ユーザー名}/.jenv/versions/oracle64-14.0.2
```

### JDKのインストール

`brew cask` でインストールしている記事が多いですが、今回はOracleからインストーラを落としてきて手動でインストールします。
以下の記事を参考にして必要なバージョンのJDKをインストールします。

- [過去バージョンのJava(JDK10以前)をインストールする方法(Mac) - Qiita](https://qiita.com/uhooi/items/c9b694e3dafa2937d81b)

複数のバージョンをインストールする場合、古いバージョンから行う必要があります。
すでに新しいバージョンがインストールされている場合、以下の記事を参考にアンインストールしてから行う必要があります。

- [Java 8のアンインストール方法(Mac) - Qiita](https://qiita.com/uhooi/items/24dc22c9f2f49a1de54b)

上記を行うとJavaの開発環境が潤います。

```bash
$ /usr/libexec/java_home -V
Matching Java Virtual Machines (10):
    14.0.2 (x86_64) "Oracle Corporation" - "Java SE 14.0.2" /Library/Java/JavaVirtualMachines/jdk-14.0.2.jdk/Contents/Home
    13.0.2 (x86_64) "Oracle Corporation" - "Java SE 13.0.2" /Library/Java/JavaVirtualMachines/jdk-13.0.2.jdk/Contents/Home
    12.0.2 (x86_64) "Oracle Corporation" - "Java SE 12.0.2" /Library/Java/JavaVirtualMachines/jdk-12.0.2.jdk/Contents/Home
    11.0.9 (x86_64) "Oracle Corporation" - "Java SE 11.0.9" /Library/Java/JavaVirtualMachines/jdk-11.0.9.jdk/Contents/Home
    10.0.2.0.13 (x86_64) "Oracle Corporation" - "Java" /Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home
    10.0.2 (x86_64) "Oracle Corporation" - "Java SE 10.0.2" /Library/Java/JavaVirtualMachines/jdk-10.0.2.jdk/Contents/Home
    9.0.4 (x86_64) "Oracle Corporation" - "Java SE 9.0.4" /Library/Java/JavaVirtualMachines/jdk-9.0.4.jdk/Contents/Home
    1.8.0_271 (x86_64) "Oracle Corporation" - "Java SE 8" /Library/Java/JavaVirtualMachines/jdk1.8.0_271.jdk/Contents/Home
    1.8.0_202 (x86_64) "Oracle Corporation" - "Java SE 8" /Library/Java/JavaVirtualMachines/jdk1.8.0_202.jdk/Contents/Home
    1.7.0_80 (x86_64) "Oracle Corporation" - "Java SE 7" /Library/Java/JavaVirtualMachines/jdk1.7.0_80.jdk/Contents/Home
/Applications/Android Studio.app/Contents/jre/jdk/Contents/Home
```

おそらくすべて使うことはないですが、何となく気持ちいいのでJDK 7〜14を全てインストールしてみました。

### .jenvフォルダの作成

`~/.jenv/versions` フォルダを手動で作成します。

```bash
$ mkdir ~/.jenv
$ mkdir ~/.jenv/versions
```

作成しないと `jenv add` で `ln: failed to create symbolic link '/Users/{ユーザー名}/.jenv/versions/oracle64-1.7.0.80': No such file or directory` エラーが発生します。
https://github.com/gcuisinier/jenv/issues/175

作成したら `.bash_profile` を再読み込みします。

```bash
$ source ~/.bash_profile
```

### jEnv環境の追加

最初はjEnvに環境が1つもありません。

```bash
$ jenv versions
* system (set by /Users/{ユーザー名}/.jenv/version)
```

`jenv add` コマンドで環境を追加します。

```bash
# jenv add {Java Virtual Machine(JVM) Homeのパス}
$ jenv add /Library/Java/JavaVirtualMachines/jdk1.7.0_80.jdk/Contents/Home
$ jenv add /Library/Java/JavaVirtualMachines/jdk1.8.0_202.jdk/Contents/Home
$ jenv add /Library/Java/JavaVirtualMachines/jdk1.8.0_271.jdk/Contents/Home
$ jenv add /Library/Java/JavaVirtualMachines/jdk-9.0.4.jdk/Contents/Home
$ jenv add /Library/Java/JavaVirtualMachines/jdk-10.0.2.jdk/Contents/Home
$ jenv add /Library/Java/JavaVirtualMachines/jdk-11.0.9.jdk/Contents/Home
$ jenv add /Library/Java/JavaVirtualMachines/jdk-12.0.2.jdk/Contents/Home
$ jenv add /Library/Java/JavaVirtualMachines/jdk-13.0.2.jdk/Contents/Home
$ jenv add /Library/Java/JavaVirtualMachines/jdk-14.0.2.jdk/Contents/Home
$ jenv add /Applications/Android\ Studio.app/Contents/jre/jdk/Contents/Home
```

JVM Homeのパスは `/usr/libexec/java_home -V` コマンドで出力されるパスのことです。

Android Studio内のJVM Homeを追加する際は、半角スペースの前に `\` を付けてエスケープしないと以下のエラーが発生するので注意です。

```shell-session
$ jenv add /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home
Warning : jenv add alias path/to/java_home is deprecated.
Please prefer to let jenv generate unique alias name by using

    $ jenv add path/to/java_home

/usr/local/Cellar/jenv/0.5.4/libexec/libexec/jenv-add: line 56: cd: Studio.app/Contents/jre/jdk/Contents/Home: No such file or directory
```

これでjEnvの環境も潤いました。

```bash
$ jenv versions
* system (set by /Users/{ユーザー名}/.jenv/version)
  1.7
  1.7.0.80
  1.8
  1.8.0.202
  1.8.0.242-release
  1.8.0.271
  10
  10.0
  10.0.2
  11
  11.0
  11.0.9
  12
  12.0
  12.0.2
  13
  13.0
  13.0.2
  14
  14.0
  14.0.2
  9
  9.0
  9.0.4
  openjdk64-1.8.0.242-release
  oracle64-1.7.0.80
  oracle64-1.8.0.202
  oracle64-1.8.0.271
  oracle64-10.0.2
  oracle64-11.0.9
  oracle64-12.0.2
  oracle64-13.0.2
  oracle64-14.0.2
  oracle64-9.0.4
```

## 操作方法

### Java環境の切替(グローバル)

`jenv global` コマンドでグローバルのJava環境を設定します。
今回はJava 9を設定します。

```bash
# グローバルのJava環境を設定する
# jenv global {環境名}
$ jenv global oracle64-9.0.4
```

Java 9でも「9」「9.0」「9.0.4」「oracle64-9.0.4」と4つの環境がありますが、公式サイトのチュートリアルでは「oracle64…」を設定しているので、ここでもそのようにしています。
何が異なるのかは調べていません。

環境が切り替わったか確認します。「oracle64-9.0.4」の先頭に「*」が付いていれば環境が切り替わっています。

```bash
$ jenv versions
  system
  1.7
  1.7.0.80
  1.8
  1.8.0.202
  1.8.0.271
  10
  10.0
  10.0.2
  11
  11.0
  11.0.9
  12
  12.0
  12.0.2
  13
  13.0
  13.0.2
  14
  14.0
  14.0.2
  9
  9.0
  9.0.4
  oracle64-1.7.0.80
  oracle64-1.8.0.202
  oracle64-1.8.0.271
  oracle64-10.0.2
  oracle64-11.0.9
  oracle64-12.0.2
  oracle64-13.0.2
  oracle64-14.0.2
* oracle64-9.0.4 (set by /Users/{ユーザー名}/.jenv/version)
```

Javaのバージョンも確認しておきます。

```bash
$ java -version
java version "9.0.4"
Java(TM) SE Runtime Environment (build 9.0.4+11)
Java HotSpot(TM) 64-Bit Server VM (build 9.0.4+11, mixed mode)
```

環境が切り替わっていることが確認できます。

もし切り替わっていない場合、すでに `JAVA_HOME` がセットされている可能性があるため、  `echo ${JAVA_HOME}` を実行して確認してください。
セットされていた場合、 `.bash_profile` などを確認してセットしている箇所を追求しましょう。

### Java環境の切替(ローカル)

ローカル（特定のフォルダ以下のみ）のJava環境を設定する場合、対象のフォルダへ移動したあとに `jenv local` コマンドで設定できます。

```bash
$ mkdir java7
$ cd java7
$ jenv local oracle64-1.7.0.80
$ java -version
java version "1.7.0_80"
Java(TM) SE Runtime Environment (build 1.7.0_80-b15)
Java HotSpot(TM) 64-Bit Server VM (build 24.80-b11, mixed mode)

# ローカル設定していないフォルダはグローバル設定が適用される
$ cd ..
$ java -version
java version "9.0.4"
Java(TM) SE Runtime Environment (build 9.0.4+11)
Java HotSpot(TM) 64-Bit Server VM (build 9.0.4+11, mixed mode)
```

## おわりに

Javaの開発環境が整いました。
これでJavaのバージョンを切り替えていろいろできます！

## 参考リンク

- [jEnv - Manage your Java environment](http://www.jenv.be)
- [【2018年版】macでAndroid開発環境を構築するための４つのこと - Qiita](https://qiita.com/Alex_mht_code/items/5fd8eed6c4b96091d581)
- [MacにJava(JDK)をインストール - Qiita](https://qiita.com/ryo0301/items/3c9a02e03b4e9a41f576)
- [Mac に Java JDK を複数バージョンインストールして管理する - kendik.net](http://kendik.hatenablog.com/entry/2015/09/02/013207)