GraalVM native-imageでJavaのコードを実行可能なバイトコードに変換

GraalVMをUbuntu 18.04にインストールしてみました。
GraalVM Community Edition 19 をUbuntu Server 18.04にインストールする

ドキュメントを見ていると、「native-image」という項目が。
Native Images

動作を確認してみます。


Javaプログラム



native-imageコマンドを利用するため、gu installでnative-imageをインストールします。


$ gu install native-image



サンプルに従い、Javaのプログラムを作成。

・HelloWorld.java


  1. public class HelloWorld {
  2.     public static void main(String[] args) {
  3.         System.out.println("Hello, World!");
  4.     }
  5. }



Javaとしてコンパイルして実行してみます。


$ javac HelloWorld.java
$ java HelloWorld
Hello, World!






Native Images



作成したHelloWorldをnative imageに変換してみます。


$ native-image HelloWorld
Build on Server(pid: 15418, port: 38627)*
[helloworld:15418]    classlist: 1,479.07 ms
[helloworld:15418]        (cap):     689.59 ms
[helloworld:15418]        setup:     923.48 ms
Error: Error compiling query code (in /tmp/SVM-7230892489949457802/PosixDirectives.c).
Compiler command
gcc /tmp/SVM-7230892489949457802/PosixDirectives.c -o /tmp/SVM-7230892489949457802/PosixDirectives
output included error: /tmp/SVM-7230892489949457802/PosixDirectives.c:77:10:
fatal error: zlib.h: そのようなファイルやディレクトリはありません
    C file contents around line 77:
    /tmp/SVM-7230892489949457802/PosixDirectives.c:76: #include <unistd.h>
    /tmp/SVM-7230892489949457802/PosixDirectives.c:77: #include <zlib.h>
    /tmp/SVM-7230892489949457802/PosixDirectives.c:78: #include <arpa/inet.h>
Error: Use -H:+ReportExceptionStackTraces to print stacktrace of underlying exception
Error: Image build request failed with exit status 1



zlibが必要とのこと。
インストールします。


$ sudo apt-get install zlib1g-dev



改めてnative-imageを実行。


$ native-image HelloWorld
Build on Server(pid: 15418, port: 38627)
[helloworld:15418]    classlist:     125.65 ms
[helloworld:15418]        (cap):     754.78 ms
[helloworld:15418]        setup: 1,691.07 ms
[helloworld:15418] (typeflow): 3,383.24 ms
[helloworld:15418]    (objects):     794.57 ms
[helloworld:15418] (features):     137.75 ms
[helloworld:15418]     analysis: 4,373.45 ms
[helloworld:15418]     (clinit):     81.05 ms
[helloworld:15418]     universe:     294.43 ms
[helloworld:15418]     (parse):     757.81 ms
[helloworld:15418]     (inline): 1,192.29 ms
[helloworld:15418]    (compile): 5,584.71 ms
[helloworld:15418]     compile: 7,750.21 ms
[helloworld:15418]        image:     277.84 ms
[helloworld:15418]        write:     83.24 ms
[helloworld:15418]     [total]: 14,700.19 ms




生成されたhelloworldバイナリを実行してみます。


$ ./helloworld
Hello, World!




サンプルのような簡単なプログラムでも、helloworldのファイルサイズは
2.5MBになりました。
もちろん、他のUbuntuにコピーしても動作します。

これはいいですね。
サーバーのログ収集や死活監視クライアントがJava製だと
「このためだけにjreインストールするのはちょっと...」
と思うことがあったので、バイナリ単体で動いてくれると便利です。




native-imageの生成条件



native-imageを生成するときはコンパイルされたclassファイルが存在していれば良く、ソースファイルは不要です。
ということは、他のJVMでコンパイルしたclassファイルでもnative-imageにできるのでは?

別の端末にインストールしているOpenJDKでビルドして試してみます。
ソースファイルを微調整。

・HelloWorld.java


  1. public class HelloWorld {
  2.     public static void main(String[] args) {
  3.         System.out.println("Hello, Symfoware!");
  4.     }
  5. }



classファイル生成


$ javac HelloWorld.java



HelloWorld.classをGraalVMをインストールしている端末にコピー。
native-imageに変換してみます。


$ native-image HelloWorld
Build on Server(pid: 15418, port: 38627)
[helloworld:15418]    classlist:     201.97 ms
Fatal error: java.lang.UnsupportedClassVersionError:
HelloWorld has been compiled by a more recent version of the Java Runtime (class file version 55.0),
this version of the Java Runtime only recognizes class file versions up to 52.0
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:468)
    at java.net.URLClassLoader.access$100(URLClassLoader.java:74)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:369)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:363)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:362)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:348)
    at com.oracle.svm.hosted.NativeImageGeneratorRunner.buildImage(NativeImageGeneratorRunner.java:239)
    at com.oracle.svm.hosted.NativeImageGeneratorRunner.build(NativeImageGeneratorRunner.java:427)
    at com.oracle.svm.hosted.server.NativeImageBuildServer.executeCompilation(NativeImageBuildServer.java:390)
    at com.oracle.svm.hosted.server.NativeImageBuildServer.lambda$processCommand$8(NativeImageBuildServer.java:327)
    at com.oracle.svm.hosted.server.NativeImageBuildServer.withJVMContext(NativeImageBuildServer.java:408)
    at com.oracle.svm.hosted.server.NativeImageBuildServer.processCommand(NativeImageBuildServer.java:324)
    at com.oracle.svm.hosted.server.NativeImageBuildServer.processRequest(NativeImageBuildServer.java:268)
    at com.oracle.svm.hosted.server.NativeImageBuildServer.lambda$serve$7(NativeImageBuildServer.java:228)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)
Error: Image build request failed with exit status 1



やっぱりダメかと思ったのですが、UnsupportedClassVersionErrorですね。
OpenJDKのバージョンを確認すると11でした。


$ java --version
openjdk 11.0.3 2019-04-16
OpenJDK Runtime Environment (build 11.0.3+7-Ubuntu-1ubuntu218.04.1)
OpenJDK 64-Bit Server VM (build 11.0.3+7-Ubuntu-1ubuntu218.04.1, mixed mode, sharing)



OpenJDK 8で改めてビルド。
これでclass file versionsは52になるはずです。


$ /usr/lib/jvm/java-8-openjdk-amd64/bin/javac HelloWorld.java



再度classファイルをコピーして、native-imageを実行。


$ native-image HelloWorld
Build on Server(pid: 15418, port: 38627)
[helloworld:15418]    classlist:     112.44 ms
[helloworld:15418]        (cap):     699.61 ms
[helloworld:15418]        setup:     968.52 ms
[helloworld:15418] (typeflow): 2,372.49 ms
[helloworld:15418]    (objects):     421.86 ms
[helloworld:15418] (features):     77.86 ms
[helloworld:15418]     analysis: 2,913.51 ms
[helloworld:15418]     (clinit):     41.64 ms
[helloworld:15418]     universe:     136.86 ms
[helloworld:15418]     (parse):     414.27 ms
[helloworld:15418]     (inline):     952.17 ms
[helloworld:15418]    (compile): 2,771.61 ms
[helloworld:15418]     compile: 4,336.30 ms
[helloworld:15418]        image:     204.96 ms
[helloworld:15418]        write:     43.26 ms
[helloworld:15418]     [total]: 8,762.90 ms




動いてくれました。


$ ./helloworld
Hello, Symfoware!


関連記事

コメント

非公開コメント

プロフィール

Author:symfo
blog形式だと探しにくいので、まとめサイト作成中です。
Symfoware まとめ

PR




検索フォーム

月別アーカイブ