SDKMANでプロジェクト毎にJavaバージョンを切り替える
kotlin プロジェクトなどの場合、プロジェクト毎に Java のバージョンを切り替えたいことがあるかと思います。
そんな時にサクッと Java のバージョンを切り替えられるSDKMANというツールがあります。
SDKMAN とは
SDKMANは Software Development Kit Managerであり、macOS などの Unix 系システム上で、SDK (フレームワークやビルドツールなど含む)を管理するためのツールです。
今回は Java のみを対象に説明しますが、Java 以外にも有名どこで言うと Gradle や Spring Boot なども管理できるみたいです。
煩雑なコマンドや設定が不要で、比較的簡単にバージョン管理ができるのが特徴です。
SDKMAN の導入
ドキュメントにある通り、基本的な導入はこれだけです。

SDKMAN のインストールが成功したら、使用したいツールのバージョンを確認し、install を実行してください。
基本のコマンドを記載します。その他のコマンドについてはドキュメントを参照してください。
-
sdk list: 使用可能ツール一覧 -
sdk list <tool-name>: ツールの使用可能バージョン一覧 -
sdk install <tool-name> <version>: 指定バージョンの install -
sdk use <tool-name> <version>: install 済みバージョンの適用 -
sdk current <tool-name>: 現在使用中のバージョン確認
※ 今回で言うと<tool-name>部分がjavaに置き換わります。
プロジェクト毎の SDKMAN 設定
ここから本題です。
SDKMAN でプロジェクト毎に Java のバージョンを切り替えたい場合、
プロジェクトの実行ディレクトリ配下にて、sdk env initを実行します。
すると、java バージョンが指定された.sdkmanrcという設定ファイルが生成されます。
# Enable auto-env through the sdkman_auto_env config
# Add key=value pairs of SDKs to use below
java=21.0.8-oracle # 適宜バージョンを指定
こちらのファイルをコミットしてプロジェクトで共有することで、プロジェクトメンバーはsdk envコマンドを実行するだけで、プロジェクト毎に Java バージョンを切り替えることができます。
この状態で./gradlew buildなどを実行すると、指定された Java バージョンでビルドが実行されます。
戻したい場合は、sdk env clearで default 設定に戻せます。

一連のコマンド実行確認例
注意点
デフォルトではsdk envコマンドは、実行したシェルセッション内でのみ有効です。
sdk envを実行した後に、ターミナルを閉じて新しいターミナルを開いた場合などは、再度sdk envを実行する必要があることには注意です。
毎回sdk envを実行するのが面倒な場合は、自動的に設定したいバージョンを読み込むsdkman_auto_env設定を有効にする方法があります。
~/.sdkman/etc/configファイル内のsdkman_auto_env設定をtrueにすると、自動的に.sdkmanrcファイルを検出して設定を読み込むようになります。
ユーザー毎のグローバルな設定にはなるので、参画時のルールや仕組みは追加する必要がありますが、頻繁に使う人は良さそうです。
詳細は Doc 参照。
AI コーディングツール使用時の注意点
AI コーディングツールを使用する際には、ツールによってはバージョンが反映されない場合があります。
私の場合は Claude Code でしか確認できていませんが、
ローカル環境でsdk current javaで使用したいバージョンが適用されていることを確認後、Claude Code で単純に./gradlew buildを実行したところ、デフォルトの Java バージョンでビルドが実行されてしまいました。
解決策としては、Claude Code に実行してもらう際は、Bash(source ~/.sdkman/bin/sdkman-init.sh && sdk env && ./gradlew build)のようにsdkman-init.sh && sdk envと同じプロセス内で実行してもらうように指示してあげましょう。
※(sdkman_auto_envが有効になっている場合は、Bash(source ~/.sdkman/bin/sdkman-init.sh && ./gradlew build)で OK です。)
# 例
## Build Commands
```bash
# ビルド
- ./gradlew [コマンド]
+ source ~/.sdkman/bin/sdkman-init.sh && sdk env && ./gradlew [コマンド]
```
※ 注意:
以下のように Claude Code 上で連続実行だと、環境変数が引き継がれない(反映されない)ため、&&で同一プロセス内で実行する必要があります。
1. Bash(source ~/.sdkman/bin/sdkman-init.sh && sdk env)
2. Bash(./gradlew build)
→ env のバージョンではなく default のバージョンが反映される
備考:
動作検証時:Claude Code: v2.0.30
Claude Code のドキュメント見る限りでは、同一のシェルプロセス内では、環境変数などは引き継がれるようです。(永続的なセッション維持)

しかし、現状ではそうはならないケースがあると、Issue が上がってるみたいです。
(いけるはずなのになんでなんだろう?と詰まりポイントでした。。)
バージョンによっては改善されていたり、アプデで再発したり、などが発生しているみたいです。
どこかのバージョンアップで改善されることを期待しています 🙏
NCDC株式会社( ncdc.co.jp/ )のエンジニアチームです。 募集中のエンジニアのポジションや、採用している技術スタックの紹介などはこちら( github.com/ncdcdev/recruitment )をご覧ください! ※エンジニア以外も記事を投稿することがあります
Discussion