runaround’s diary

なんとなく、つれづれ

ちょっぴりGraalVMと仲良くなってみた

話題になった当時に猛者がいじり倒し終わっているのですが、私は今から触りますよ、GraalVM。


とてもわかりやすい文章をじゅくちょーさんが本に書いて下さってます。
www.sakatakoichi.com


みんなのJava
gihyo.jp


まぁ、ちょっと目的があって調べていたのですが、忘れないようにメモっておこうと思います。
直近何かで使う機会がなさそうなので・・・。
以下、みんJavaに書かれていることを読んで試してみたログになります。


GraalVMとは

  • あらゆる言語コードを実行する機能と能力をもつ仮想マシン
  • 対応OSは macOSLinuxWindowsは試験的対応⇨次にMicronaut触ろうと思ってるんでこの時点でバイバーイ)
  • 言語間で相互利用できる、パフォーマンスも十分
  • EE(エンタープライズ)、CE(コミュニティ)がありCEは無償

環境確認と設定

とりあえず今入ってるJavaバージョンを確認しました。

$  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)

ちょっと古めかなー?と思ってJava 11を11.0.7にアプデしておいた。


次はGrarrlVMをダウンロードするぞぅ。

www.graalvm.org

使用したのは以下。Macなので。

graalvm-ce-java11-darwin-amd64-20.1.0.tar.gz

あと、19.3以前はJava8にしか対応してなかったらしい。
19.3以降はJava8と11から選べる、と。


とりあえず解凍しますかね。

$  tar zxvf graalvm-ce-java11-darwin-amd64-20.1.0.tar.gz


次はPathを通しておく。
解凍した中にあるbinディレクトリまでのパスを設定した。既存のPathに区切り文字(コロン)でくっつけたらいいのね。
あとPATH設定しくったら、lsコマンドすらわからなくなるというMacのターミナルちゃん( ༎ຶŎ༎ຶ )
qiita.com

$  open ~/.bash_profile

# 編集したら反映
$  source ~/.bash_profile

#確認
$  echo $PATH


さて、認識してるかな?

$  java -version
openjdk version "11.0.7" 2020-04-14
OpenJDK Runtime Environment GraalVM CE 20.1.0 (build 11.0.7+10-jvmci-20.1-b02)
OpenJDK 64-Bit Server VM GraalVM CE 20.1.0 (build 11.0.7+10-jvmci-20.1-b02, mixed mode, sharing)

わーい!認識したー!

動かしてみるっ

本にはjs動く、と書いてあるのでどれどれっと・・・ん?

$  js
[ERROR] Failed to construct terminal; falling back to unsupported
java.io.IOException: Cannot run program "sh": error=2, No such file or directory
	at java.lang.ProcessBuilder.start(ProcessBuilder.java:1128)
	at java.lang.ProcessBuilder.start(ProcessBuilder.java:1071)
	at jline.internal.TerminalLineSettings.exec(TerminalLineSettings.java:308)
	at jline.internal.TerminalLineSettings.stty(TerminalLineSettings.java:282)
	at jline.internal.TerminalLineSettings.get(TerminalLineSettings.java:143)
	at jline.internal.TerminalLineSettings.<init>(TerminalLineSettings.java:108)
	at jline.internal.TerminalLineSettings.getSettings(TerminalLineSettings.java:123)
	at jline.UnixTerminal.<init>(UnixTerminal.java:60)
	at jline.UnixTerminal.<init>(UnixTerminal.java:50)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:490)
	at java.lang.Class.newInstance(DynamicHub.java:835)
	at jline.TerminalFactory.getFlavor(TerminalFactory.java:205)
	at jline.TerminalFactory.create(TerminalFactory.java:96)
	at jline.TerminalFactory.get(TerminalFactory.java:180)
	at jline.TerminalFactory.get(TerminalFactory.java:186)
	at jline.console.ConsoleReader.<init>(ConsoleReader.java:244)
	at jline.console.ConsoleReader.<init>(ConsoleReader.java:236)
	at jline.console.ConsoleReader.<init>(ConsoleReader.java:228)
	at com.oracle.truffle.js.shell.JLineConsoleHandler.createConsole(JLineConsoleHandler.java:59)
	at com.oracle.truffle.js.shell.JLineConsoleHandler.<init>(JLineConsoleHandler.java:55)
	at com.oracle.truffle.js.shell.JSLauncher.setupConsole(JSLauncher.java:413)
	at com.oracle.truffle.js.shell.JSLauncher.runREPL(JSLauncher.java:370)
	at com.oracle.truffle.js.shell.JSLauncher.executeScripts(JSLauncher.java:337)
	at com.oracle.truffle.js.shell.JSLauncher.launch(JSLauncher.java:86)
	at org.graalvm.launcher.AbstractLanguageLauncher.launch(AbstractLanguageLauncher.java:121)
	at org.graalvm.launcher.AbstractLanguageLauncher.launch(AbstractLanguageLauncher.java:70)
	at com.oracle.truffle.js.shell.JSLauncher.main(JSLauncher.java:72)
Caused by: java.io.IOException: error=2, No such file or directory
	at com.oracle.svm.jni.JNIJavaCallWrappers.jniInvoke_VA_LIST:Ljava_io_IOException_2_0002e_0003cinit_0003e_00028Ljava_lang_String_2_00029V(JNIJavaCallWrappers.java:0)
	at java.lang.ProcessImpl.forkAndExec(ProcessImpl.java)
	at java.lang.ProcessImpl.<init>(ProcessImpl.java:340)
	at java.lang.ProcessImpl.start(ProcessImpl.java:271)
	at java.lang.ProcessBuilder.start(ProcessBuilder.java:1107)
	... 26 more

ええー・・・エラーを派手に吐いているものの、ちゃんと立ち上がるんですよね。
おそらくjline(Java で高機能な CUI コンソールを作るためのライブラリ)が上手く動いてない様子?
SBTでエラーでた、って書き込みをよく見かけるけれど・・・🧐
とりあえずbash_profileに以下を設定してみた。

export TERM=xterm-color

とか設定してみたけど直らないなぁ。一旦ここはスキップ・・・
と思ったら直りましたw
sourceだけじゃダメでPC再起動したらいけたみたい。


本に書いてある通り、jsを動かしたり、jsからJavaを呼び出してみたり。
おおお!動くぞ!(当たり前)

> console.log("test")
test
> const array = new (Java.type("int[]"))(2)
> array[1] = 100
100

ネイティブイメージインストール

せっかくなのでネイティブイメージもやってみよう。

  • 実行対象OSで直接実行できるバイナリを作成できる
  • 起動時間を短縮できる
  • 起動にJVMが不要なのでメモリ使用を抑えられる
  • とはいえ、長時間起動しているアプリケーションには向かないかな・・・瞬発力が必要なアプリケーション向き?


まずはインストール。

$  gu install native-image
Downloading: Component catalog from www.graalvm.org
Processing Component: Native Image
Downloading: Component native-image: Native Image  from github.com
Installing new component: Native Image (org.graalvm.native-image, version 20.1.0)


実行するアプリケーションを作っておく。

class HelloWorld {
    public static void main(String... args) {
    	System.out.println("Hello, World!");
    }
}


コンパイルしておく。

$  javac HelloWorld.java

$  ls -la
total 16
drwxr-xr-x  4 run  staff  128  5 25 13:24 .
drwxr-xr-x  5 run  staff  160  5 25 09:52 ..
-rw-r--r--  1 run  staff  427  5 25 13:24 HelloWorld.class
-rw-r--r--@ 1 run  staff  115  5 25 13:22 HelloWorld.java


ネイティブイメージをビルドする。

$  native-image HelloWorld
Build on Server(pid: 806, port: 49544)*
[helloworld:806]    classlist:   2,408.33 ms,  0.96 GB
[helloworld:806]        (cap):   2,805.19 ms,  0.96 GB
[helloworld:806]        setup:   5,459.09 ms,  0.96 GB
[helloworld:806]     (clinit):     259.97 ms,  1.21 GB
[helloworld:806]   (typeflow):   7,568.45 ms,  1.21 GB
[helloworld:806]    (objects):   4,221.81 ms,  1.21 GB
[helloworld:806]   (features):     347.56 ms,  1.21 GB
[helloworld:806]     analysis:  12,688.20 ms,  1.21 GB
[helloworld:806]     universe:     456.88 ms,  1.21 GB
[helloworld:806]      (parse):   2,733.96 ms,  1.67 GB
[helloworld:806]     (inline):   1,386.15 ms,  1.67 GB
[helloworld:806]    (compile):  13,954.39 ms,  2.28 GB
[helloworld:806]      compile:  18,786.93 ms,  2.28 GB
[helloworld:806]        image:   1,520.23 ms,  2.28 GB
[helloworld:806]        write:     441.40 ms,  2.28 GB
[helloworld:806]      [total]:  42,418.71 ms,  2.28 GB


おー、全て小文字のヤツがネイティブイメージらしい。

$  ls -la
total 13088
drwxr-xr-x  5 run  staff      160  5 25 13:27 .
drwxr-xr-x  5 run  staff      160  5 25 09:52 ..
-rw-r--r--  1 run  staff      427  5 25 13:24 HelloWorld.class
-rw-r--r--@ 1 run  staff      115  5 25 13:22 HelloWorld.java
-rwxr-xr-x  1 run  staff  6690316  5 25 13:27 helloworld


ネイティブイメージを実行してみたら・・・あ、ちゃんと動いたー。

$  ./helloworld
Hello, World!

ということで

ちょっとだけGraalVMと仲良く・・・なれ・・た・・・気がする。
次はMicronautを乗っけてくところをメモっておこうかと思いますが・・・気が向いたら。
せめてモノリシックなアプリケーション(テンプレはThymeleafあたりで)作りたいなぁー。
このあたりを参考に。
github.com