Macで多様なJavaバージョンとディストリビューションを管理：HomebrewとjEnvの活用

# Homebrewのインストール

- Homebrewのサイトを参照
    - https://brew.sh

## `homebrew-cask-versions`の導入

:::note warn
[Homebrew/homebrew-cask](https://github.com/Homebrew/homebrew-cask)に統合されたため、導入不要になった
:::

- https://github.com/Homebrew/homebrew-cask-versions
    - 最新バージョン以外のインストールに必要

```shell
$ brew tap homebrew/cask-versions
```

# 利用可能なディストリビューション

## [OpenJDK](https://openjdk.org/)
- **特徴:** Javaの基本実装、広範囲のプラットフォーム対応
- **注意点:** 限定的な長期サポート、定期的なアップデートとセキュリティ更新の必要性
- **商用利用:** 可能

## [Eclipse Temurin](https://adoptium.net/temurin/)
- **特徴:** パフォーマンスとセキュリティに重点、多様なJavaバージョンサポート
- **注意点:** コミュニティ主導で商用サポート限定、独自機能と互換性の潜在的問題
- **商用利用:** 可能

## [Amazon Corretto](https://aws.amazon.com/jp/corretto/)
- **特徴:** AWS最適化、長期サポート、セキュリティパッチ
- **注意点:** AWS外環境でのパフォーマンス非保証、AWSに特化
- **商用利用:** 可能

## [Oracle JDK](https://www.oracle.com/jp/java/technologies/downloads/)
- **特徴:** Oracleによる公式Java版、高パフォーマンスとセキュリティ
- **注意点:** 有料ライセンスが必要、Oracleのサポートポリシー遵守
- **商用利用:** 有料ライセンスを購入すれば可能

## [Azul Zulu](https://www.azul.com/downloads/?package=jdk#)
- **特徴:** 商用サポート、多様なプラットフォーム互換性
- **注意点:** 商用ライセンス要、バージョンによる機能差異
- **商用利用:** 商用ライセンスを購入すれば可能

## [GraalVM](https://www.graalvm.org/)
- **特徴:** 多言語対応、高性能、柔軟な実行と最適化
- **注意点:** 設定の複雑さ、特化機能、Javaライブラリ互換性の限定
- **商用利用:** ライセンス条項に従えば可能

## [Microsoft Build of OpenJDK](https://www.microsoft.com/openjdk)
- **特徴:** Microsoftによるビルド、Azureとの統合、クロスプラットフォーム
- **注意点:** Microsoftエコシステム内利用重視、他プラットフォームサポート限定
- **商用利用:** 可能

## [SapMachine](https://sap.github.io/SapMachine/)
- **特徴:** SAP製品互換性、定期更新とサポート
- **注意点:** SAP外環境での利点少ない、SAPアプリケーション最適化
- **商用利用:** 可能

## [IBM Semeru](https://developer.ibm.com/languages/java/semeru-runtimes/)
- **特徴:** 高性能、クラウド環境に最適化、Eclipse OpenJ9を使用
- **注意点:** 特定のクラウド環境に最適化されているため、他の環境でのパフォーマンスは異なる可能性あり
- **商用利用:** 可能

# インストール

## Java 21のインストール

```shell
$ brew install openjdk@21
$ brew install --cask temurin@21
$ brew install --cask corretto@21
$ brew install --cask oracle-jdk@21
$ brew install --cask zulu@21
$ brew install --cask graalvm-jdk@21
$ brew install --cask microsoft-openjdk@21
$ brew install --cask sapmachine-jdk
$ brew install --cask semeru-jdk-open@21
```

## Java 17のインストール

```shell
$ brew install openjdk@17
$ brew install --cask temurin@17
$ brew install --cask corretto@17
$ brew install --cask zulu@17
$ brew install --cask graalvm-jdk@17
$ brew install --cask microsoft-openjdk@17
$ brew install --cask semeru-jdk-open@17
```

## Java 11のインストール

```shell
$ brew install openjdk@11
$ brew install --cask temurin@11
$ brew install --cask corretto@11
$ brew install --cask zulu@11
$ brew install --cask microsoft-openjdk@11
$ brew install --cask semeru-jdk-open@11
```

## Java 8のインストール

```shell
$ brew install openjdk@8
$ brew install --cask temurin@8
$ brew install --cask corretto@8
$ brew install --cask zulu@8
$ brew install --cask semeru-jdk-open@8
```

# インストール済みJDK(`JAVA_HOME`)の確認

- `/usr/libexec/java_home`コマンドを利用して、インストールされているJDKを確認できる

```shell
$ /usr/libexec/java_home -V
Matching Java Virtual Machines (9):
    21.0.1 (x86_64) "Homebrew" - "OpenJDK 21.0.1" /usr/local/Cellar/openjdk/21.0.1/libexec/openjdk.jdk/Contents/Home
    21.0.1 (x86_64) "Eclipse Adoptium" - "OpenJDK 21.0.1" /Users/seijikohara/Library/Java/JavaVirtualMachines/temurin-21.0.1/Contents/Home
    17.0.9 (x86_64) "Eclipse Adoptium" - "OpenJDK 17.0.9" /Users/seijikohara/Library/Java/JavaVirtualMachines/temurin-17.0.9/Contents/Home
    17.0.9 (x86_64) "Amazon.com Inc." - "Amazon Corretto 17" /Users/seijikohara/Library/Java/JavaVirtualMachines/corretto-17.0.9/Contents/Home
    17.0.8.1 (x86_64) "Eclipse Adoptium" - "OpenJDK 17.0.8.1" /Users/seijikohara/Library/Java/JavaVirtualMachines/temurin-17.0.8.1/Contents/Home
    17.0.8 (x86_64) "Amazon.com Inc." - "Amazon Corretto 17" /Users/seijikohara/Library/Java/JavaVirtualMachines/corretto-17.0.8/Contents/Home
    17.0.8 (x86_64) "Amazon.com Inc." - "Amazon Corretto 17" /Users/seijikohara/Library/Java/JavaVirtualMachines/corretto-17.0.8.1/Contents/Home
    17.0.8 (x86_64) "Eclipse Adoptium" - "OpenJDK 17.0.8" /Users/seijikohara/Library/Java/JavaVirtualMachines/temurin-17.0.8/Contents/Home
    11.0.21 (x86_64) "Homebrew" - "OpenJDK 11.0.21" /usr/local/Cellar/openjdk@11/11.0.21/libexec/openjdk.jdk/Contents/Home
/usr/local/Cellar/openjdk/21.0.1/libexec/openjdk.jdk/Contents/Home

$ /usr/libexec/java_home --help
Usage: java_home [options...]
    Returns the path to a Java home directory from the current user's settings.

Options:
    [-v/--version   <version>]       Filter versions (as if JAVA_VERSION had been set in the environment).
    [-a/--arch      <architecture>]  Filter architecture (as if JAVA_ARCH had been set in the environment).
    [-F/--failfast]                  Fail when filters return no JVMs, do not continue with default.
    [   --exec      <command> ...]   Execute the $JAVA_HOME/bin/<command> with the remaining arguments.
    [-X/--xml]                       Print full JVM list and additional data as XML plist.
    [-V/--verbose]                   Print full JVM list with architectures.
    [-h/--help]                      This usage information.
```

# JDKの切り替え

- [OSXでJavaのバージョンを切り替える](https://qiita.com/ringo/items/db58b34dc02a941b297f)
    - 環境変数`JAVA_HOME`にインストールしたJDKのパスを指定する
    - 利用しているシェルに応じて`.bashrc`, `.zshrc`ファイルに追記する

```shell
$ export JAVA_HOME=/usr/local/Cellar/openjdk/21.0.1/libexec/openjdk.jdk/Contents/Home
$ PATH=${JAVA_HOME}/bin:${PATH}
```

# jEnvの利用

- jEnvを導入するこで、Javaのバージョンを切り替えが簡単になる
    - 参考: https://github.com/jenv/jenv

## jEnvのインストール

- Homebrewでインストール

```shell
$ brew install jenv
```

- `PATH`を設定
    - 使用するシェルにより異なる

```shell
# Shell: zsh
$ echo 'export PATH="$HOME/.jenv/bin:$PATH"' >> ~/.zshrc
$ echo 'eval "$(jenv init -)"' >> ~/.zshrc

# Shell: bash
$ echo 'export PATH="$HOME/.jenv/bin:$PATH"' >> ~/.bash_profile
$ echo 'eval "$(jenv init -)"' >> ~/.bash_profile
```

- ディレクトリを作成

```shell
$ cd ~
$ mkdir ~/.jenv/versions
```

## jEnvにJDKを追加

- JDKはHomebrew Caskでインストールする
    - インストールしたJDKをjEnvに追加する

```shell
$ jenv add /usr/local/Cellar/openjdk/21.0.1/libexec/openjdk.jdk/Contents/Home
```

## jEnvに追加されているJDKの一覧

- 先頭に`*`が表示されているJDKが有効化されている

```shell
$ jenv versions
  system
* 21.0 (set by /Users/[ユーザ名]/.jenv/version)
  21.0.1
  temurin64-21.0.1
```

## Javaの切り替え

- `jenv versions`で出力される任意のバージョンへ切り替えられる

### グローバル

```shell
$ jenv global 21.0
$ jenv versions
  system
* 21.0 (set by /Users/[ユーザ名]/.jenv/version)
  21.0.1
  temurin64-21.0.1
$ java -version
openjdk version "21.0.1" 2023-10-17 LTS
OpenJDK Runtime Environment Temurin-21.0.1+12 (build 21.0.1+12-LTS)
OpenJDK 64-Bit Server VM Temurin-21.0.1+12 (build 21.0.1+12-LTS, mixed mode)
```

### ローカル

- 特定のディレクトリのみに適用する
    - コマンドを実行したディレクトリに`.java-version`ファイルが作成され、指定されたバージョンのJDKが利用可能となる

```shell
$ jenv local 11.0
$ jenv versions
  system
  1.8
  1.8.0.222
* 11.0 (set by [jenv localを実行したディレクトリ]/.java-version)
  11.0.2
  openjdk64-1.8.0.222
  openjdk64-11.0.2
$ java -version
openjdk version "11.0.2" 2019-01-15
OpenJDK Runtime Environment 18.9 (build 11.0.2+9)
OpenJDK 64-Bit Server VM 18.9 (build 11.0.2+9, mixed mode)
$ cat .java-version
11.0
```

## 環境変数`JAVA_HOME`の自動設定

- 自動的に`JAVA_HOME`を設定するには`enable-plugin export`を実行する
    - 自動設定を解除するには`disable-plugin export`を実行する

```shell
$ jenv enable-plugin export
```