この記事は JPOUG Advent Calendar 2020 の6日目です。
5日目は wmo6hashさんの記事『ベランピング空間がライブ配信スタジオになるまでに揃えた仕事道具 - wmo6hash::blog』でした。
はじめに
先日、JJUG CCC のイベントで Picocli という Java 製コマンドラインツールのフレームワークについてのセッションで GraalVM を用いてネイティブイメージが手軽に作成できることを知りました。
- remkop/picocli: Picocli is a modern framework for building powerful, user-friendly, GraalVM-enabled command line apps with ease.
- jjug-ccc-2020-fall - JavaとpicocliとGraalVMでときめくCLIアプリを作ろう | ConfEngine - Conference Platform
- GraalVM, PicocliとJavaでときめくネイティブコマンドラインアプリを作ろう
※JJUG CCC 2019 FALLの資料
- GraalVM, PicocliとJavaでときめくネイティブコマンドラインアプリを作ろう
Oracle 主導で開発されている GraalVM については Java 関連のセッションや記事でたびたび見聞きしたことがありましたが、Java 開発から遠ざかっている身としては関係ないだろうなと思いつつも、「Java 製コマンドラインツール」というところでふと SQLcl が浮かび、
と思ったのが本記事のきっかけです。sqlclをGraalVMでネイティブ化。
— Kazuhiro YOSHIKAWA (@yoshikaw) November 7, 2020
なんかの記事書けそう?
TL; DR
すでにタイトルが結論なのですが、Java VM でのコード実行の仕組みやネイティブアプリケーションについての知識が十分とはいえない状態で、いきなり GraalVM でクローズドソースの Java コマンドラインツールをネイティブイメージにするのはハードルが高く実現出来ませんでした。
とはいえ様々なサイトを参考にさせていただき、あともう少しで動かせそうな所までいった気になりましたので、何らかの参考になると思い試行した過程を記します。GraalVM でのネイティブイメージの作成がどのようなものか雰囲気だけでも掴んでいただければ幸いです。
- GraalVMでガチの gRPC ワーカーをNative Image にしてみたときの学び - Qiita
- GraalVM の概要と、Native Image 化によるSpring Boot 爆速化の夢
- Guide to GraalVM (JJUG CCC 2019 Fall)
- GraalVM Native Imageが見せた未来
- SpringとGrarlVM Native Image -2019/12-
- Javaのコンソールプログラムの起動をGraalVMのnative-imageで高速にしてみる - Qiita
環境
- OS: Oracle Linux 8.3
- Oracle Linux Vagrant Boxes | Oracle, Software. Hardware. Complete.
- メモリは足りなくなったのでVagrant標準の2GBから6GBに増やしています
- OpenJDK 11.0.9+11-LTS
- Oracle Linux Vagrant Boxes | Oracle, Software. Hardware. Complete.
- SQLcl:
- GraalVM: based on OpenJDK version 11.0.9
- SQL*Plus: Instant Client 19.9
- Oracle Database: XE 18c / Oracle Linux 7.9 ※SQLcl実行環境とは別
はじめから SQLcl はそのような用途ではないかもしれませんが、やはり Java VM 起動時のオーバーヘッドがどうしてもあります。
[SQL*Plus] INSTANCE_NAME ---------------- XE 385,899 ns [SQLcl] OpenJDK 11 INSTANCE_NAME ---------------- XE 3,252,258 ns [SQLcl] GraalVM 20.3.0 INSTANCE_NAME ---------------- XE 3,435,483 ns
ネイティブイメージ作成環境準備
GraalVM のインストール自体はダウンロードした tar ボールを展開してパスを通すだけです。今回は SQLcl とあわせて /opt 以下に展開しました。
$ ls -l /opt 合計 0 drwxr-xr-x. 8 root root 136 Nov 15 05:51 VBoxGuestAdditions-6.1.16 lrwxrwxrwx. 1 root root 24 Dec 5 22:20 graalvm -> graalvm-ce-java11-20.3.0 drwxr-xr-x. 10 root root 232 Dec 5 23:34 graalvm-ce-java11-20.3.0 lrwxrwxrwx. 1 root root 21 Dec 5 22:09 sqlcl -> sqlcl-20.3.0.274.1916 drwxr-xr-x. 4 root root 68 Sep 30 19:16 sqlcl-20.3.0.274.1916つぎに GraalVM のネイティブイメージの処理を行うコンポーネントを GraalVM Updater コマンド(gu) でインストールします。
$ sudo /opt/graalvm/bin/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.3.0) $ /opt/graalvm/bin/gu list ComponentId Version Component name Origin -------------------------------------------------------------------------------- js 20.3.0 Graal.js graalvm 20.3.0 GraalVM Core native-image 20.3.0 Native Image github.com $ /opt/graalvm/bin/native-image --version GraalVM Version 20.3.0 (Java Version 11.0.9+10-jvmci-20.3-b06)ネイティブビルドに必要な OS パッケージもインストールしておきます。
$ sudo yum install gcc glibc-devel zlib-devel $ sudo yum install gcc-c++ libstdc++-devel
SQLcl実行環境の解析
Linux 版の SQLcl は bin/sql
というシェルスクリプトで Java のコマンドラインが隠蔽されていますが、ネイティブイメージに変換するには jar ファイルや実行クラス、クラスパスを特定する必要があります。
# # Run the tool. # function run { if [ "m$SQLCL_DEBUG" != "m" ]; then echo "JAVA=$JAVA" echo "JAVA_OPTS=${APP_VM_OPTS[@]}" echo "DEBUG=$DEBUG" echo "CPLIST=$CPLIST" echo "LD_LIBRARY_PATH=$LD_LIBRARY_PATH" echo "$JAVA $CUSTOM_JDBC $CYGWIN "${APP_VM_OPTS[@]}" -client $SQLCL_DEBUG -cp "$CPLIST" oracle.dbtools.raptor.scriptrunner.cmdline.SqlCli " fi $JAVA $CUSTOM_JDBC $CYGWIN "${APP_VM_OPTS[@]}" -client $SQLCL_DEBUG -cp "$CPLIST" oracle.dbtools.raptor.scriptrunner.cmdline.SqlCli "$@" }シェルスクリプトから実行クラスは
oracle.dbtools.raptor.scriptrunner.cmdline.SqlCli
であることが分かります。
実行時のクラスパスを確認するため、SQLcl を起動して Ctrl-Z でプロセスを中断した状態で ps コマンドでコマンドラインを確認します。
$ sql SQLcl: 日 12 06 13:42:23 2020のリリース20.3 Production Copyright (c) 1982, 2020, Oracle. All rights reserved. ユーザー名 (''?) [1]+ 停止 sql
$ ps -axwf | grep [S]qlCli 15499 pts/4 Tl 0:03 | \_ java -Duser.language=ja -Duser.region=JP -Dfile.encoding=utf8 -Djava.awt.headless=true -Dapple.awt.UIElement=true -Xss30M -XX:+IgnoreUnrecognizedVMOptions --add-opens=java.prefs/java.util.prefs=ALL-UNNAMED -client -cp /opt/sqlcl/lib/dbtools-sqlcl.jar:/opt/sqlcl/lib/jansi.jar:/opt/sqlcl/lib/drivers/*:/opt/sqlcl/lib/ext/*:/opt/sqlcl/../rdbms/jlib/xdb6.jar:/opt/sqlcl/../jdbc/lib/ojdbc8.jar:/opt/sqlcl/../jlib/orai18n-utility.jar:/opt/sqlcl/../jlib/orai18n-mapping.jar:/opt/sqlcl/../jlib/orai18n.jar:/opt/sqlcl/../modules/oracle.xdk/xmlparserv2.jar:/opt/sqlcl/lib/slf4j-api.jar:/opt/sqlcl/lib/slf4j-jdk14.jar:/opt/sqlcl/lib/javax.json.jar:/opt/sqlcl/lib/javax.json-api.jar:/opt/sqlcl/lib/xmlparserv2.jar:/opt/sqlcl/lib/jaxb-api.jar:/opt/sqlcl/lib/commons-logging.jar:/opt/sqlcl/lib/orai18n.jar:/opt/sqlcl/lib/xmlparserv2-sans-jaxp-services.jar:/opt/sqlcl/lib/orai18n-collation.jar:/opt/sqlcl/lib/jackson-jr-stree.jar:/opt/sqlcl/lib/jackson-jr-objects.jar:/opt/sqlcl/lib/xdb6.jar:/opt/sqlcl/lib/jackson-core.jar:/opt/sqlcl/lib/ST4.jar:/opt/sqlcl/lib/oraclepki.jar:/opt/sqlcl/lib/jackson-annotations.jar:/opt/sqlcl/lib/osdt_core.jar:/opt/sqlcl/lib/httpmime.jar:/opt/sqlcl/lib/osdt_cert.jar:/opt/sqlcl/lib/httpcore.jar:/opt/sqlcl/lib/orajsoda.jar:/opt/sqlcl/lib/httpclient.jar:/opt/sqlcl/lib/orai18n-utility.jar:/opt/sqlcl/lib/ojdbc8.jar:/opt/sqlcl/lib/dbtools-sqlcl.jar:/opt/sqlcl/lib/dbtools-net.jar:/opt/sqlcl/lib/dbtools-http.jar:/opt/sqlcl/lib/dbtools-common.jar:/opt/sqlcl/lib/dbtools-data.jar:/opt/sqlcl/lib/orai18n-servlet.jar:/opt/sqlcl/lib/sshd-contrib.jar:/opt/sqlcl/lib/sshd-common.jar:/opt/sqlcl/lib/sshd-core.jar:/opt/sqlcl/lib/commons-codec.jar:/opt/sqlcl/lib/jdbcrest.jar:/opt/sqlcl/lib/orai18n-mapping.jar:/opt/sqlcl/lib/jline.jar:/opt/sqlcl/lib/antlr-runtime.jar:/opt/sqlcl/lib/guava.jar: oracle.dbtools.raptor.scriptrunner.cmdline.SqlCliシェルスクリプトから実行クラスは分かりますが、このクラスファイルが含まれる jar ファイルを指定する必要があるので、雑に grep で探します。
$ grep oracle.dbtools.raptor.scriptrunner.cmdline.SqlCli /opt/sqlcl/lib/*.jar バイナリファイル /opt/sqlcl/lib/dbtools-sqlcl.jar に一致しました
ネイティブイメージの作成
これで native-image
に与える情報は揃いましたので実行してみます。
$ /opt/graalvm/bin/native-image -jar /opt/sqlcl/lib/dbtools-sqlcl.jar [dbtools-sqlcl:15565] classlist: 5,027.87 ms, 1.56 GB [dbtools-sqlcl:15565] (cap): 746.11 ms, 1.56 GB [dbtools-sqlcl:15565] setup: 2,730.79 ms, 1.56 GB [dbtools-sqlcl:15565] (clinit): 386.75 ms, 1.92 GB [dbtools-sqlcl:15565] analysis: 22,965.04 ms, 1.92 GB Warning: Aborting stand-alone image build due to unsupported features Warning: Use -H:+ReportExceptionStackTraces to print stacktrace of underlying exception [dbtools-sqlcl:15646] classlist: 2,679.95 ms, 1.14 GB [dbtools-sqlcl:15646] (cap): 908.58 ms, 1.14 GB [dbtools-sqlcl:15646] setup: 3,227.98 ms, 1.61 GB [dbtools-sqlcl:15646] (clinit): 191.37 ms, 1.68 GB [dbtools-sqlcl:15646] (typeflow): 6,341.68 ms, 1.68 GB [dbtools-sqlcl:15646] (objects): 3,855.94 ms, 1.68 GB [dbtools-sqlcl:15646] (features): 160.73 ms, 1.68 GB [dbtools-sqlcl:15646] analysis: 10,758.78 ms, 1.68 GB [dbtools-sqlcl:15646] universe: 653.84 ms, 1.68 GB [dbtools-sqlcl:15646] (parse): 2,155.27 ms, 1.68 GB [dbtools-sqlcl:15646] (inline): 1,586.00 ms, 1.68 GB [dbtools-sqlcl:15646] (compile): 10,286.97 ms, 1.94 GB [dbtools-sqlcl:15646] compile: 14,515.11 ms, 1.94 GB [dbtools-sqlcl:15646] image: 750.27 ms, 1.95 GB [dbtools-sqlcl:15646] write: 219.12 ms, 1.95 GB [dbtools-sqlcl:15646] [total]: 33,086.83 ms, 1.95 GB Warning: Image 'dbtools-sqlcl' is a fallback image that requires a JDK for execution (use --no-fallback to suppress fallback image generation and to print more detailed information why a fallback image was necessary). $ ls -lh dbtools-sqlcl -rwxrwxr-x. 1 vagrant vagrant 5.0M Dec 6 13:57 dbtools-sqlcl何やらコンパイルはできたようですが、必要な情報が揃ってなくて JDK が必要な状態でネイティブにはほど遠そうです。 しかし、その場合にどうやって実行してよいかは調べきれませんでした。
$ ./dbtools-sqlcl Exception in thread "main" java.lang.NoClassDefFoundError: oracle/dbtools/cmdline/SqlCliDataInit at oracle.dbtools.raptor.scriptrunner.cmdline.SqlCli.この後ひたすらスタックトレースに表示されるメッセージ((SqlCli.java:242) at oracle.dbtools.raptor.scriptrunner.cmdline.SqlCli.main(SqlCli.java:465) Caused by: java.lang.ClassNotFoundException: oracle.dbtools.cmdline.SqlCliDataInit at java.net.URLClassLoader.findClass(URLClassLoader.java:382) at java.lang.ClassLoader.loadClass(ClassLoader.java:418) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:352) at java.lang.ClassLoader.loadClass(ClassLoader.java:351) ... 2 more Exception in thread "cleanup" java.lang.NoClassDefFoundError: oracle/xml/parser/v2/DOMParser at oracle.dbtools.raptor.console.HistoryParser.processXML(HistoryParser.java:82) at oracle.dbtools.raptor.console.MultiLineHistory.load(MultiLineHistory.java:788) at oracle.dbtools.raptor.console.MultiLineHistory.getInstance(MultiLineHistory.java:400) at oracle.dbtools.raptor.scriptrunner.cmdline.SqlCli$3.run(SqlCli.java:628) Caused by: java.lang.ClassNotFoundException: oracle.xml.parser.v2.DOMParser at java.net.URLClassLoader.findClass(URLClassLoader.java:382) at java.lang.ClassLoader.loadClass(ClassLoader.java:418) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:352) at java.lang.ClassLoader.loadClass(ClassLoader.java:351) ... 4 more
--no-fallback
)を追加してビルドしてはまた別のエラー、というのを延々と繰り返してなかなか先に進めなくなった頃、ネイティブイメージビルド時に付加する情報を GraalVM が javaagent として解析できることを知りました。
native-image-agent の出力先ディレクトリ(ここでは META-INF
)を作成し、SQLcl を native-image-agent を有効化した GraalVM で起動して、データベースに接続して適当なクエリを実行します。
$ mkdir META-INF $ env JAVA_HOME=/opt/graalvm JAVA_TOOL_OPTIONS=-agentlib:native-image-agent=config-output-dir=META-INF/native-image /opt/sqlcl/bin/sql system/oracle@ol7.vbox/xepdb1 Picked up JAVA_TOOL_OPTIONS: -agentlib:native-image-agent=config-output-dir=META-INF/native-image SQLcl: 日 12月 06 14:13:07 2020のリリース20.3 Production Copyright (c) 1982, 2020, Oracle. All rights reserved. Last Successful login time: 日 12月 06 2020 14:13:09 +09:00 接続先: Oracle Database 18c Express Edition Release 18.0.0.0.0 - Production Version 18.4.0.0.0 SQL> select instance_name from v$instance; INSTANCE_NAME ________________ XE SQL> quit Oracle Database 18c Express Edition Release 18.0.0.0.0 - Production Version 18.4.0.0.0から切断されましたすると以下のようなファイルが作成されます。
$ find META-INF -type f -exec ls -l {} + -rw-rw-r--. 1 vagrant vagrant 1740 Dec 6 14:13 META-INF/native-image/jni-config.json -rw-rw-r--. 1 vagrant vagrant 4 Dec 6 14:13 META-INF/native-image/proxy-config.json -rw-rw-r--. 1 vagrant vagrant 47004 Dec 6 14:13 META-INF/native-image/reflect-config.json -rw-rw-r--. 1 vagrant vagrant 2385 Dec 6 14:13 META-INF/native-image/resource-config.jsonこの解析情報を
-H:ConfigurationFileDirectories=META-INF/native-image
のように指定しますが、この解析情報も 100% ではないので、
refrect-config.json を編集して、
--- ../../META-INF/native-image/reflect-config.json.20201206 2020-12-06 02:43:33.189102201 +0900 +++ ../../META-INF/native-image/reflect-config.json 2020-12-06 03:57:22.893790943 +0900 @@ -1415,10 +1415,6 @@ "methods":[{"name":"再びエラーメッセージと格闘して最終的に以下のコマンドラインで native-image コマンドが途中で終了しないところまで辿り着きました。(","parameterTypes":[] }] }, { - "name":"org.graalvm.compiler.hotspot.management.AggregatedMemoryPoolBean", - "allPublicConstructors":true -}, -{ "name":"short[]" }, {
$CP
は SQLcl 実行時に確認した値を変数に設定)
$ /opt/graalvm/bin/native-image -jar /opt/sqlcl/lib/dbtools-sqlcl.jar \ -cp $CP \ --allow-incomplete-classpath \ --no-fallback \ --trace-class-initialization=org.slf4j.impl.StaticLoggerBinder,org.slf4j.LoggerFactory,org.slf4j.impl.JDK14LoggerAdapter \ --initialize-at-build-time=org.slf4j.impl.StaticLoggerBinder \ --initialize-at-build-time=org.slf4j.impl.JDK14LoggerAdapter \ --initialize-at-build-time=org.slf4j.LoggerFactory \ --initialize-at-run-time=com.sun.org.apache.xml.internal.serializer.XMLEntities \ --initialize-at-build-time=com.sun.org.apache.xml.internal.serializer.ToXMLStream \ -H:+ReportExceptionStackTraces \ -H:+PrintAnalysisCallTree \ -H:ConfigurationFileDirectories=META-INF/native-image \ -H:IncludeResourceBundles=oracle.xml.mesg.XMLResourceBundle \ -H:IncludeResourceBundles=oracle.dbtools.util.Messages \ -H:IncludeResourceBundles=oracle.dbtools.raptor.newscriptrunner.commands.Messages \ -H:IncludeResourceBundles=oracle.dbtools.raptor.newscriptrunner.commands.alias.Messages \ -H:IncludeResourceBundles=oracle.dbtools.raptor.scriptrunner.cmdline.Messages \ -H:IncludeResourceBundles=oracle.dbtools.raptor.scriptrunner.cmdline.editor.Messages \ -H:IncludeResourceBundles=oracle.dbtools.raptor.scriptrunner.commands.Messages \ -H:IncludeResourceBundles=oracle.dbtools.util.Messages \ [dbtools-sqlcl:16371] classlist: 5,133.60 ms, 1.19 GB WARNING: Field org.fusesource.jansi.internal.CLibrary.HAVE_TTYNAME not found. [dbtools-sqlcl:16371] (cap): 700.77 ms, 1.19 GB WARNING: Could not resolve oracle.dbtools.raptor.scriptrunner.commands.lb.lbCommand for reflection configuration. WARNING: Could not resolve oracle.dbtools.raptor.scriptrunner.commands.liquibase.liquibaseCommand for reflection configuration. WARNING: Could not resolve oracle.dbtools.raptor.scriptrunner.commands.modeler.ModelerCommand for reflection configuration. [dbtools-sqlcl:16371] setup: 2,670.55 ms, 1.19 GB WARNING: Could not register reflection metadata for org.apache.commons.logging.impl.Log4JLogger. Reason: java.lang.NoClassDefFoundError: org/apache/log4j/Priority. WARNING: Could not register reflection metadata for org.apache.commons.logging.impl.Log4JLogger. Reason: java.lang.NoClassDefFoundError: org/apache/log4j/Priority. WARNING: Could not register reflection metadata for org.apache.commons.logging.impl.Log4JLogger. Reason: java.lang.NoClassDefFoundError: org/apache/log4j/Priority. WARNING: Could not register reflection metadata for org.apache.commons.logging.impl.Log4JLogger. Reason: java.lang.NoClassDefFoundError: org/apache/log4j/Priority. WARNING: Could not register reflection metadata for org.apache.commons.logging.impl.Log4JLogger. Reason: java.lang.NoClassDefFoundError: org/apache/log4j/Priority. WARNING: Could not register reflection metadata for org.apache.commons.logging.impl.Log4JLogger. Reason: java.lang.NoClassDefFoundError: org/apache/log4j/Priority. WARNING: Could not register reflection metadata for org.apache.commons.logging.impl.Log4JLogger. Reason: java.lang.NoClassDefFoundError: org/apache/log4j/Priority. [dbtools-sqlcl:16371] (clinit): 1,254.18 ms, 2.48 GB [dbtools-sqlcl:16371] (typeflow): 50,500.06 ms, 2.48 GB [dbtools-sqlcl:16371] (objects): 37,113.20 ms, 2.48 GB [dbtools-sqlcl:16371] (features): 2,835.28 ms, 2.48 GB [dbtools-sqlcl:16371] analysis: 95,310.34 ms, 2.48 GB Printing call tree to /home/vagrant/work/2/reports/call_tree_dbtools-sqlcl_20201206_143328.txt Printing list of used methods to /home/vagrant/work/2/reports/used_methods_dbtools-sqlcl_20201206_143338.txt Printing list of used classes to /home/vagrant/work/2/reports/used_classes_dbtools-sqlcl_20201206_143338.txt Printing list of used packages to /home/vagrant/work/2/reports/used_packages_dbtools-sqlcl_20201206_143338.txt [dbtools-sqlcl:16371] universe: 3,296.59 ms, 2.52 GB [dbtools-sqlcl:16371] (parse): 19,504.37 ms, 2.99 GB [dbtools-sqlcl:16371] (inline): 32,865.40 ms, 3.93 GB [dbtools-sqlcl:16371] (compile): 104,992.03 ms, 4.02 GB [dbtools-sqlcl:16371] compile: 162,929.43 ms, 4.02 GB [dbtools-sqlcl:16371] image: 8,199.64 ms, 4.07 GB [dbtools-sqlcl:16371] write: 2,051.35 ms, 4.07 GB [dbtools-sqlcl:16371] [total]: 312,012.26 ms, 4.07 GB $ ls -lh ./dbtools-sqlcl -rwxrwxr-x. 1 vagrant vagrant 86M Dec 6 14:36 ./dbtools-sqlclこの実行時のエラー(
UnsupportedFeatureError
)を検索するといくつも Issue は見つかるのですが、今回は解決のヒントになりそうな情報は見つけられず諦めました。
$ ./dbtools-sqlcl Exception in thread "main" com.oracle.svm.core.jdk.UnsupportedFeatureError: Setting a custom URLStreamHandlerFactory. at com.oracle.svm.core.util.VMError.unsupportedFeature(VMError.java:87) at java.net.URL.setURLStreamHandlerFactory(URL.java:77) at oracle.dbtools.common.utils.DBUrlStreamHandler.register(DBUrlStreamHandler.java:23) at oracle.dbtools.raptor.scriptrunner.cmdline.SqlCli.(SqlCli.java:243) at oracle.dbtools.raptor.scriptrunner.cmdline.SqlCli.main(SqlCli.java:465)
おわりに
思いつきでできるほどネイティブイメージ化は簡単ではなかったというのが率直な感想です。とはいえクラウドの FaaS サービスも課金時間の単位が秒からミリ秒と細かくなり、起動時間の短さは運用費用の削減により直結するようになりました。また昔は速度向上のためのネイティブコンパイルというと実行環境が限られて扱いづらいイメージがありましたが、今日日の実行環境はコンテナで容易にパッケージできるようになっていますので Quarkus のようなフットプリントを小さくしてネイティブイメージでより高速に実行できる実行環境が出てきたのも頷けるなと思いました。
- New for AWS Lambda – 1ms Billing Granularity Adds Cost Savings | AWS News Blog
- AWS Lambda の新機能 – コンテナイメージのサポート | Amazon Web Services ブログ
- Getting started with Quarkus | Red Hat Developer
- Oracle Database Multilingual Engine (MLE) Based on JavaScript module
- 詳説GraalVM(4) GraalVMが組み込まれたデータベース - Fight the Future
おまけ
外部ライブラリの多い SQLcl は仕方ないにしても、単一クラスのシンプルな処理ならネイティブイメージ余裕でしょとか思っていましたたけど甘かったです。。。(Hello Worldなら確認できました)
import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; public class JdbcOracleTest { public static void main(String[] args) { try { Class.forName("oracle.jdbc.driver.OracleDriver"); Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@//ol7.vbox/xepdb1", "system", "oracle"); Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery("select dummy from dual"); while (rs.next()) { System.out.println("結果:" + rs.getString("dummy")); } rs.close(); stmt.close(); conn.close(); } catch (Exception e) { e.printStackTrace(); } } }
$ /opt/graalvm/bin/javac JdbcOracleTest.java $ /opt/graalvm/bin/java -cp .:/opt/sqlcl/lib/ojdbc8.jar JdbcOracleTest 結果:X
$ /opt/graalvm/bin/native-image -cp .:/opt/sqlcl/lib/ojdbc8.jar JdbcOracleTest --no-fallback --allow-incomplete-classpath --enable-all-security-services [jdbcoracletest:16724] classlist: 3,058.80 ms, 0.96 GB [jdbcoracletest:16724] (cap): 735.68 ms, 0.96 GB [jdbcoracletest:16724] setup: 2,673.17 ms, 0.96 GB [jdbcoracletest:16724] (clinit): 1,057.87 ms, 2.04 GB [jdbcoracletest:16724] (typeflow): 34,635.93 ms, 2.04 GB [jdbcoracletest:16724] (objects): 24,049.71 ms, 2.04 GB [jdbcoracletest:16724] (features): 1,993.17 ms, 2.04 GB [jdbcoracletest:16724] analysis: 63,299.88 ms, 2.04 GB [jdbcoracletest:16724] universe: 2,371.29 ms, 2.04 GB [jdbcoracletest:16724] (parse): 16,256.38 ms, 2.20 GB [jdbcoracletest:16724] (inline): 14,330.76 ms, 3.10 GB [jdbcoracletest:16724] (compile): 121,753.47 ms, 3.11 GB [jdbcoracletest:16724] compile: 155,411.12 ms, 3.11 GB [jdbcoracletest:16724] image: 5,368.44 ms, 3.11 GB [jdbcoracletest:16724] write: 914.31 ms, 3.11 GB [jdbcoracletest:16724] [total]: 233,498.95 ms, 3.11 GB $ ls -lh JdbcOracleTest.class jdbcoracletest -rw-rw-r--. 1 vagrant vagrant 1.8K Dec 6 14:55 JdbcOracleTest.class -rwxrwxr-x. 1 vagrant vagrant 45M Dec 6 15:03 jdbcoracletest $ ./jdbcoracletest Exception in thread "main" com.oracle.svm.core.jdk.UnsupportedFeatureError: ObjectInputStream.readObject() at com.oracle.svm.core.util.VMError.unsupportedFeature(VMError.java:87) at java.io.ObjectInputStream.readObject(ObjectInputStream.java:53) at oracle.sql.ConverterArchive.readObj(ConverterArchive.java:400) at oracle.sql.converter.CharacterConverterJDBC.getInstance(CharacterConverterJDBC.java:143) at oracle.jdbc.driver.DynamicByteArray$1.run(DynamicByteArray.java:881) at java.security.AccessController.doPrivileged(AccessController.java:84) at oracle.jdbc.driver.DynamicByteArray.(DynamicByteArray.java:877) at com.oracle.svm.core.classinitialization.ClassInitializationInfo.invokeClassInitializer(ClassInitializationInfo.java:351) at com.oracle.svm.core.classinitialization.ClassInitializationInfo.initialize(ClassInitializationInfo.java:271) at oracle.jdbc.driver.T4CStatement.configureRowData(T4CStatement.java:440) at oracle.jdbc.driver.OracleStatement.initStatement(OracleStatement.java:831) at oracle.jdbc.driver.OracleStatement. (OracleStatement.java:772) at oracle.jdbc.driver.T4CStatement. (T4CStatement.java:1230) at oracle.jdbc.driver.T4CDriverExtension.allocateStatement(T4CDriverExtension.java:63) at oracle.jdbc.driver.PhysicalConnection.createStatement(PhysicalConnection.java:1645) at oracle.jdbc.driver.PhysicalConnection.createStatement(PhysicalConnection.java:1626) at oracle.jdbc.driver.PhysicalConnection.createStatement(PhysicalConnection.java:1595) at JdbcOracleTest.main(JdbcOracleTest.java:11)
こんにちは。
返信削除勉強させていただきます!