ちょっと真の本題で書いたことを調べようと思って、いろいろ調べた結果の備忘録です。
でも、真の本題の方は、いまいち解決していないという。。
Java のバージョンについて
Java については、まず、言語そのものと、その動作環境である JVM があり、それらについて、公式の仕様の部分と、公式 (Oracle) やその他さまざまなところが出している実装の部分があります。
Oracle が出している Java の仕様は Java SE (Standard Edition) と呼ばれます。
アプリケーション実装に踏み込んだ仕様である Java EE (Enterprise Edition) (現在は Jakarta EE として移管) や組み込み用途での Java ME (Micro Edition) というのがあった影響で、 Java SE と名付けられていますが、完全に歴史的経緯ですね。
Oracle による Java 実装は、通称 Oracle JDK と呼ばれています。
また、準公式的な位置づけのオープンソース Java 実装として OpenJDK というのもあります。Oracle 買収前の Sun Microsystems が始めたもののようです。
そして、昨今 Java を取り巻く環境が大きく変わってきています。
他のプログラミング言語の進歩に取り残される形になった Java が変化に対応しようとする中での動きなのでしょう。
まず、短いスパンで、細かい機能修正を加えたバージョンアップが行われるようになりました。
2017-09 リリースの Java 9 以降、現在のところ、半年に1回、メジャーバージョンが更新されています。
そして Java 11 以降ですが、 Oracle のライセンス形態が変わり、公式版のいわゆる Oracle JDK 自体は利用が有償化されるようになりました。
それに変わって、今まで Oracle JDK に含まれていた機能で OpenJDK に入っていなかった部分も OpenJDK に移管され、オープンソース化されました。
OpenJDK 自体は無償で利用できますし、この流れを受けて、 OpenJDK を独自にビルドしたディストリビューションも各社・コミュニティが公開するようになりました。
つまり、今まで Java といえば、だいたい Java 6-8 あたりの Oracle JDK だけ使っていればよかったのが、各ベンダ別のさまざまなバージョンの "Java" が普及するようになっています。
References
- Oracle JDK Releases for Java 11 and Later | Oracle Java Platform Group, Product Management Blog
- 「Java8からJava11」で何が起きたのか、どう環境構築すればいいのか - Qiita
- JDK、Oracle JDK、OpenJDK、Java SEってなに? - Qiita
- オープンソースのOracle JDKとOpenJDKを比較
macOS での Java のバージョン管理
本題です。主には SDKMAN! を使った方法と /usr/libexec/java_home
を使った方法があります。
SDKMAN! を使った方法
SDKMAN! は、 JVM 系のバージョン管理ツールで、 Java だけではなくて、 JVM 系の言語 (Groovy, Scala など) やミドルウェアのバージョン管理までやってくれます。
もともとは GVM (Groovy enVironment Manager) だったらしい。
各バージョンの検索・インストールから、各 scope でのバージョン切り替えまでをやってくれます。詳細はここでは書きません。
内部的に JAVA_HOME
を切り替えているようです。
/usr/libexec/java_home
を使った方法
こちらの方法では、インストーラや Homebrew を使ってインストールした Java のバージョンの切り替えを行えます。
例えば Homebrew で以下のように AdoptOpenJDK 最新版をインストールします。
macOS Catalina では、以下のように --no-quarantine
option が必要です(*)。
$ brew cask install adoptopenjdk --no-quarantine
(*) ちなみに--no-quarantine
optionをつけ忘れた場合でもxattr -d com.apple.quarantine /Library/Java/JavaVirtualMachines/adoptopenjdk-13.0.1.jdk
のようにすれば検疫属性を削除して起動できるようになります。
インストールした Java の一覧は、以下のコマンドで確認できます。 /Library/Java/JavaVirtualMachines/
配下にあるものだけが表示されるようです。
ちなみに、このディレクトリはシステムベースのもので、 SDKMAN! はユーザベースでモジュールを管理することから、 SDKMAN! でインストールした Java はこのディレクトリには配置されず、したがってこのコマンドの結果には出てきません。
SDKMAN! のドキュメントにも、 /usr/libexec/java_home
を使った方法との互換性はないと書かれています。
$ /usr/libexec/java_home -V
特定のバージョンの Java のパスを得たい場合は、小文字の -v
オプションを利用する。
$ /usr/libexec/java_home -v 13.0
オプション無しで実行すれば、デフォルト (たぶん最新バージョン) の Java のパスが取得されます。
$ /usr/libexec/java_home
特定のバージョンに JAVA_HOME
を切り替える場合は、以下のようにします。
$ export JAVA_HOME=`/usr/libexec/java_home -v 13.0`
一時的にデフォルト以外の Java バージョンを使って、実行することも可能です。
$ /usr/libexec/java_home -v 13.0 --exec java -version
お察しのとおりですが、 /usr/libexec/java_home
は Java のバージョンを見るだけで、そのビルドを発行しているベンダまでは見てくれないので、複数ベンダの Java を入れた場合はうまく対処してくれないみたいです。
/Library/Java/JavaVirtualMachines/<JAVA>/Contents/Info.plist
に書いてある JVMVersion
のバージョンで比較をしているようですね。
ベンダも含めて管理したい場合は、 jEnv を使うのが良さそうです。
References
- sdkmanでJavaのインストール - mike-neckのブログ
- java_home and JAVA_HOME on macOS - Notes for Geeks - Medium
- Working with multiple Java versions in MacOS - Bruno Frascino - Medium
- HomebrewでインストールできるJDKまとめ(2019年11月時点) - Qiita
- macos - Why doesn't /usr/libexec/java_home recognize JDK 1.8? - Ask Different
- Unsigned error when using this cask on Catalina 10.15.1 · Issue #267 · AdoptOpenJDK/homebrew-openjdk
- macos - How can I change Mac OS's default Java VM returned from /usr/libexec/java_home - Stack Overflow
- FAQ · sdkman/sdkman-cli Wiki
- Installed JDK in Mac, But can show it with system command
/usr/libexec/java_home
· Issue #638 · sdkman/sdkman-cli
Homebrew で Java 1.8+ is required to install this formula
みたいなエラーが出る場合
真の本題です。
SDKMAN! で入れた Java しか無い状態で、 Homebrew で bundletool をインストールしようとしたところ、以下のエラーが発生しました。
$ brew install bundletool
bundletool: Java 1.8+ is required to install this formula.
Install AdoptOpenJDK with Homebrew Cask:
brew cask install adoptopenjdk
Error: An unsatisfied requirement failed this build.
bundletool の formula を見たところ、 depends_on :java => "1.8+"
の指定があり、これを満たせていないようです。
SDKMAN! で入れた場合にも JAVA_HOME
は入っているし、Homebrew のソースコード をちらっと見るには、 JAVA_HOME
に適切な Java が入っていれば問題なさそうなんですが...
あまりじっくり見ていないので、何がダメなのかちょっと良くわかりませんでした。誰か分かる人教えてください><
とりあえず言われるがままに、 Homebrew で AdoptOpenJDK をインストールして、特に JAVA_HOME
の切り替えなどはせずに再度 brew install bundletool
を実行すると、うまくインストールできました。
$ brew cask install adoptopenjdk --no-quarantine
Homebrew でのインストール時に必要なだけで、後は SDKMAN! でインストールした Java でも動作しそうなので、すぐにアンインストールしても問題なさそうです。
$ brew cask uninstall adoptopenjdk
References