この記事は Javaのカレンダー 2日目の記事になります。
はじめに
最近コードを触ることから離れていたのですが、最近少し時間ができたので、前から気になっていたGraalVMを触ってみることにしました。
本番環境で動かしている会社もあるんだろうか?
ということで、やってみた系の記事になります。
GraalVMとは
Javaコードからネイティブバイナリを作る事ができるツールです。
ネイティブアプリを作れるということは、JVMを利用する場合の良くない特徴の、JVM特有の起動の遅さやJVMのランタイムを環境に入れなければ動作できないことを回避することができます。
つまり、アプリ高速に起動できたり、アプリ単体で起動できるということです!
もしかしたらアプリのパフォーマンスも高いのでは?
しかし、デメリットもあります。ネイティブアプリになるため、ビルドした環境と同じ環境でしか動かなかったり、JVMがOSなどの環境の違いを埋めていた部分の影響を受けることになります。
ただ、最近はdockerが使われることも多くなってきており、JVMがなくても同じ環境を作り出せるため、ネイティブアプリのデメリットを最小にしながら、起動スピードやパフォーマンスなどのメリットを最大化出来る可能性があります。
ということで、実験として触ってみたいと思って、個人PCで動作をさせてみたいと思って、今回の環境を作ってみようと思いました。
今回利用した環境
個人で普段使っているPCでMacBook Pro M1を使います。
メモリ 8 GB
OSのバージョンはVentura (13.6.1)
スペックは普通かな。
開発するならメモリはもっと欲しいけど、最近はブラウザとslackとzoomとdiscordしか使わないので、お手頃なPCにしてました。
GraalVMセットアップ
早速環境セットアップします!
ダウンロード
こちらのページからダウンロードできそうです。
https://www.graalvm.org/downloads/#
VMからネイティブは色々とハマりそうな気がするので、枯れた古いバージョンのJava17をダウンロードしました。
ちゃんと動かせたらバージョンアップしてみたいですね。
gzファイルがダウンロードできたので、解凍して適当なフォルダに展開しておきます。
graalvm-jdk-17_macos-x64_bin.tar.gz
Javaフォルダに移動しておきます。
sudo mv graalvm-jdk-17.0.9+11.1 /Library/Java/JavaVirtualMachines
パスの設定
実行パスを設定します。
export PATH=/Library/Java/JavaVirtualMachines/graalvm-jdk-17.0.9+11.1/Contents/Home/bin:$PATH
JAVA_HOMEも設定しておきます。
export JAVA_HOME=/Library/Java/JavaVirtualMachines/graalvm-jdk-17.0.9+11.1/Contents/Home
exportだとウィンドウを閉じると設定が消えてしまうので、zshrcに書いておいてもいいかも。
まあ、IDEを使うなら、その中でプロジェクト設定できるはず!
ここではこのまま行きます。
動作確認!
java -version
java version "17.0.9" 2023-10-17 LTS
Java(TM) SE Runtime Environment Oracle GraalVM 17.0.9+11.1 (build 17.0.9+11-LTS-jvmci-23.0-b21)
Java HotSpot(TM) 64-Bit Server VM Oracle GraalVM 17.0.9+11.1 (build 17.0.9+11-LTS-jvmci-23.0-b21, mixed mode, sharing)
うん!動いた!
実装コード
では、早速コードを書いて動かしてみたいと思います!
Javaコード書いてやってみる
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}
Java21ではないので、まだ public static String[] argsが
必要です。
ビルドします!
javac HelloWorld.java
成功すると何も表示されません。失敗したときだけエラーがでます。
まずは普通にvmで動かしてみます
java HelloWorld
Hello, World!
動きましたー
では、ネイティブイメージを作ります!
native-image HelloWorld
結構時間掛かる。
数行のHello Worldなのに数分は掛かります。。
Produced artifacts:
/hello_world/helloworld (executable)
================================================================================
Finished generating 'helloworld' in 1m 26s.
他のことをしながら待っていると
helloworldのネイティブイメージができたっぽいです!
動かしてみます!
./helloworld
zsh: segmentation fault ./helloworld
動かない、、、、、。
このあと色々頑張ったのだけど動かなかった・・・。
ということで、本当は挫折の記事ではなくで、動かしてみてパフォーマンス検証とかしたかったのだけど、数時間Macのアップデートなどに格闘した結果、この記事のタイトルが変わり、挫折した話となりました。
ハマったところ
java -version
のコマンドを実行したときに以下の警告が出てきました。
このコマンドで解決
sudo xattr -r -d com.apple.quarantine /Library/Java/JavaVirtualMachines/graalvm-jdk-17.0.9+11.1/
ダウンロードしたばかりのファイルはクリーンな属性を付与してあげる必要があるみたいです。
native-image
で完成したネイティブイメージを実行しようとしたら動かない!
このIssueはCloseされているんだけど、これっぽい?
ここでコメントされている対処を進めてみます。
こちらのサイトでXCodeをダウンロードするっぽいですが、
https://developer.apple.com/download/all/?q=Xcode
IDEのXCodeは必要ないので、Command Line Tools をいれることにしました。
MacのバージョンとあっているCommand Line Toolsを選ばないと古くても、新しくてもインストールできませんでした。。
Venturaだったので、Command Line Tools のバージョンは14をやってみるとインストールができました。 (OSのバージョンとXCodeのバージョンを揃えて欲しい。。。)
(VenturaはOSバージョン13なのですが、XCodeバージョンの13は入れることができず、正しいバージョンは14でした。。)
インストールできたので進めようとすると、また違うエラー!
xcode-select --install
xcode-select: error: command line tools are already installed, use "Software Update" in System Settings to install updates
普通にXCodeを入れた方が早そうなので、XCodeを入れることにしました。
でも、バージョンは14をダウンロードします。 (最新のXCodeバージョンは15でした)
ダウンロードと解凍に結構時間がかかります。
インストールが済んだら進めていきます。
sudo xcode-select -s /Applications/Xcode.app/Contents/Developer
成功すると特に何も起きません。
sudo xcodebuild -license
By typing 'agree' you are agreeing to the terms of the software license agreements. Type 'print' to print them or anything else to cancel, [agree, print, cancel]
agree
とタイプして、ライセンス承認します。
動作確認します
xcodebuild -version
Xcode 14.3.1
Build version 14E300c
ちゃんと動いた!
この環境で、ネイティブイメージを作り直し、実行し直しても同じエラーで動かず😢
ちゃんとアップデートも実行してみました
softwareupdate --all --install --force
Software Update Tool
Finding available software
アップデートを待ちます。
どんなに待ってもアップデートが完了せず。。
softwareupdate
のコマンドでOSのアップデートも走るみたいでしたが、コンソール上からはアップデートの実行が完了せず、システム設定からアップデートを実行しました
OS再インストール後にも、ネイティブイメージを作り直し、実行し直しても同じエラーで動かず。。
あとは、MacOSが今はVenturaなのですが、最新のSonomaにアップデートするかどうか迷ったのですが、ちょっと今回は諦めました。
まとめ
ネイティブイメージ化するだけかなって思っていたのですが、見事にネイティブイメージのデメリットを踏んで、環境周りのハマりどころにハマってしまいました。
Macの環境依存は他のOSよりも独特のところも多く、ハマりどころも多いのかもしれません。
mac環境のビルドはなかなか厳しいです。次はDockerを使ってビルドし手もいいかもですね。
ここまでだと普通のJVMの偉大さを感じるだけですが、また機会があればチャレンジしたいと思います。
この問題の解決方法を知っている方が居たらコメント頂けると嬉しいです!