2020/12/06

GraalVMでSQLclをネイティブイメージにしてみたかった話

この記事は JPOUG Advent Calendar 2020 の6日目です。
5日目は wmo6hashさんの記事『ベランピング空間がライブ配信スタジオになるまでに揃えた仕事道具 - wmo6hash::blog』でした。

はじめに

先日、JJUG CCC のイベントで Picocli という Java 製コマンドラインツールのフレームワークについてのセッションで GraalVM を用いてネイティブイメージが手軽に作成できることを知りました。

Oracle 主導で開発されている GraalVM については Java 関連のセッションや記事でたびたび見聞きしたことがありましたが、Java 開発から遠ざかっている身としては関係ないだろうなと思いつつも、「Java 製コマンドラインツール」というところでふと SQLcl が浮かび、

と思ったのが本記事のきっかけです。

TL; DR

すでにタイトルが結論なのですが、Java VM でのコード実行の仕組みやネイティブアプリケーションについての知識が十分とはいえない状態で、いきなり GraalVM でクローズドソースの Java コマンドラインツールをネイティブイメージにするのはハードルが高く実現出来ませんでした。

とはいえ様々なサイトを参考にさせていただき、あともう少しで動かせそうな所までいった気になりましたので、何らかの参考になると思い試行した過程を記します。GraalVM でのネイティブイメージの作成がどのようなものか雰囲気だけでも掴んでいただければ幸いです。

環境

このような構成で Oracle Database に接続してシンプルな SQL を実行する処理の時間を SQL*Plus、SQLcl、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":"","parameterTypes":[] }]
 },
 {
-  "name":"org.graalvm.compiler.hotspot.management.AggregatedMemoryPoolBean",
-  "allPublicConstructors":true
-},
-{
   "name":"short[]"
 },
 {
再びエラーメッセージと格闘して最終的に以下のコマンドラインで native-image コマンドが途中で終了しないところまで辿り着きました。($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 のようなフットプリントを小さくしてネイティブイメージでより高速に実行できる実行環境が出てきたのも頷けるなと思いました。

GraalVM はデータベースからも実行可能な高速な多言語環境を目的の一つとしているようですので、ネイティブイメージ生成装置としてだけではなく引き続き注目してゆこうと思います。

おまけ

外部ライブラリの多い 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)

1 件のコメント: