これは、なにをしたくて書いたもの?
こちらの資料を見ていて、「あれ?ネイティブイメージでのヒープサイズってどうやって指定するんだろう?」と思いまして。
GraalVM(SubstrateVM)を使ったネイティブイメージにした時って、実行ファイルに引数を指定するしかなくなるので、
javaコマンドの時に渡していた「-X」なオプションやシステムプロパティってどうなるんだろうという疑問がありました。
今回は、そのあたりを調べてみようかと。
環境
今回の環境は、こちら。
$ java -version openjdk version "1.8.0_212" OpenJDK Runtime Environment (build 1.8.0_212-20190420092731.buildslave.jdk8u-src-tar--b03) OpenJDK GraalVM CE 19.0.0 (build 25.212-b03-jvmci-19-b01, mixed mode) $ native-image --version GraalVM Version 19.0.0 CE
サンプルプログラム
先に、簡単なプログラムを用意してみます。
アプリケーションの起動引数を出力するだけの、簡単なアプリケーションです。
PrintArgs.java
public class PrintArgs { public static void main(String... args) { System.out.println("Print program args:"); for (String arg : args) { System.out.printf(" %s%n", arg); } } }
こちらをコンパイルして
$ javac PrintArgs.java
実行。「-Xmx」とか入っていて引数の内容がやや作為的ですが、そのまま出力されます。
$ java PrintArgs -Xmx512M -Xms512M foo bar Print program args: -Xmx512M -Xms512M foo bar
では、ネイティブイメージにビルドしてみます。
$ native-image PrintArgs print-args
javaコマンドの時と同じ引数を指定して実行してみると、なんと「-Xmx」などがなくなりました。
$ ./print-args -Xmx512M -Xms512M foo bar Print program args: foo bar
試しに、他の場所に入れてもやっぱりなくなります。
$ ./print-args hoge foo bar -Xmx512M -Xms512M test Print program args: hoge foo bar test
この点を、ちょっと追ってみましょう。
GraalVMのソースコードから、コマンドライン引数解析処理を見る
最初に参照した資料では、ヒープサイズの指定については「HeapPolicy.java」を見るとよいという記載がありました。
確かに、最大ヒープサイズあたりの記述があります。
ここで、このヒープの最大サイズ(-Xmx)などを扱っているXOptionsというクラスを見てみましょう。
graal/XOptions.java at vm-19.0.0 · oracle/graal · GitHub
どうやら、以下の4つを認識するようです。
※正確には、前方一致みたいですが(epoch、value)
- -Xmn
- -Xmx
- -Xms
- -Xss
これらをパースする処理を呼び出すのはどこだろう?と見てみると、このあたりみたいですね。
さらにその呼び出し元。
RuntimeOptionParser#parseAndConsumeAllOptionsの中身を見ると、XOptionsの他にも3つほど引数のパース処理があります。
見てみると、「-XX:」と「-Dgraal.」で始まるオプション、
※「-XX:」はフラグ(+または-)での指定、「-Dgraal.」はname=valueの形式になるようです
そして、「-D<key>=<value>」なオプション(いわゆるシステムプロパティ)を対象としているようです。
なるほど、このあたりはGraalVM(SubstrateVM)で面倒を見ているんですねぇ。
確認してみる
では、ちょっと試してみましょう。いくつかオプションをつけてみて…
$ ./print-args -Xmx512M foo -Dkey=value bar -XX:+AggressiveOpts error: Could not find option 'AggressiveOpts'. Use -XX:PrintFlags= to list all available options.
コケてしまいました。「-XX:」で指定できるオプションには、制限がありそうです。
エラーメッセージ通り、「-XX:PrintFlags=」をつけてみると、指定可能な「-XX:」なオプションが表示されます。
$ ./print-args -XX:PrintFlags= -XX:±EagerSnippets Eagerly construct extra snippet info. Default: - (disabled). -XX:±InstallSegfaultHandler Install segfault handler that prints register contents and full Java stacktrace. Default: enabled for an executable, disabled for a shared library. -XX:MaximumHeapSizePercent=80 The maximum heap size as percent of physical memory. -XX:MaximumYoungGenerationSizePercent=10 The maximum size of the young generation as a percent of the maximum heap size. -XX:PercentTimeInIncrementalCollection=50 Percentage of time that should be spent in young generation collections. -XX:PrintFlags=... Show available options based on comma-separated option-types (allowed categories: User, Expert, Debug). Default: None -XX:±PrintGC Print summary GC information after each collection. Default: - (disabled). -XX:±PrintGCSummary Print summary GC information after main completion. Default: - (disabled). -XX:±PrintGCTimeStamps Print a time stamp at each collection, if +PrintGC or +VerboseGC. Default: - (disabled). -XX:±PrintGCTimes Print the time for each of the phases of each collection, if +VerboseGC. Default: - (disabled). -XX:±PrintHeapShape Print the shape of the heap before and after each collection, if +VerboseGC. Default: - (disabled). -XX:±SafepointPromptnessFailureIsFatal Are safepoint promptness failures fatal?. Default: + (enabled). -XX:SafepointPromptnessFailureNanos=0 Exit the VM if I can not come to a safepoint in this many nanoseconds. 0 implies forever. -XX:SafepointPromptnessWarningNanos=0 Print a warning if I can not come to a safepoint in this many nanoseconds. 0 implies forever. -XX:TearDownFailureNanos=0 The number of nanoseconds before tearing down an isolate gives a failure message. 0 implies no message. -XX:TearDownWarningNanos=0 The number of nanoseconds before and between which tearing down an isolate gives a warning message. 0 implies no warning. -XX:±TraceHeapChunks Trace heap chunks during collections, if +VerboseGC and +PrintHeapShape. Default: - (disabled). -XX:±TraceVMOperations Trace VMOperation execution. Default: - (disabled). -XX:±VerboseGC Print more information about the heap before and after each collection. Default: - (disabled).
では、ちょっと変えてみましょう。
$ ./print-args -Xmx512M foo -Dkey=value bar -XX:+PrintGC Print program args: foo bar
今度はOKでした。
ところで、「-Dgraal.」の場合はなにを指定するんでしょう?
これは、「-Dgraal.PrintFlags=」を指定することで確認できます。
$ ./print-args -Dgraal.PrintFlags= -Dgraal.±EagerSnippets Eagerly construct extra snippet info. Default: - (disabled). -Dgraal.±InstallSegfaultHandler Install segfault handler that prints register contents and full Java stacktrace. Default: enabled for an executable, disabled for a shared library. -Dgraal.MaximumHeapSizePercent=80 The maximum heap size as percent of physical memory. -Dgraal.MaximumYoungGenerationSizePercent=10 The maximum size of the young generation as a percent of the maximum heap size. -Dgraal.PercentTimeInIncrementalCollection=50 Percentage of time that should be spent in young generation collections. -Dgraal.PrintFlags=... Show available options based on comma-separated option-types (allowed categories: User, Expert, Debug). Default: None -Dgraal.±PrintGC Print summary GC information after each collection. Default: - (disabled). -Dgraal.±PrintGCSummary Print summary GC information after main completion. Default: - (disabled). -Dgraal.±PrintGCTimeStamps Print a time stamp at each collection, if +PrintGC or +VerboseGC. Default: - (disabled). -Dgraal.±PrintGCTimes Print the time for each of the phases of each collection, if +VerboseGC. Default: - (disabled). -Dgraal.±PrintHeapShape Print the shape of the heap before and after each collection, if +VerboseGC. Default: - (disabled). -Dgraal.±SafepointPromptnessFailureIsFatal Are safepoint promptness failures fatal?. Default: + (enabled). -Dgraal.SafepointPromptnessFailureNanos=0 Exit the VM if I can not come to a safepoint in this many nanoseconds. 0 implies forever. -Dgraal.SafepointPromptnessWarningNanos=0 Print a warning if I can not come to a safepoint in this many nanoseconds. 0 implies forever. -Dgraal.TearDownFailureNanos=0 The number of nanoseconds before tearing down an isolate gives a failure message. 0 implies no message. -Dgraal.TearDownWarningNanos=0 The number of nanoseconds before and between which tearing down an isolate gives a warning message. 0 implies no warning. -Dgraal.±TraceHeapChunks Trace heap chunks during collections, if +VerboseGC and +PrintHeapShape. Default: - (disabled). -Dgraal.±TraceVMOperations Trace VMOperation execution. Default: - (disabled). -Dgraal.±VerboseGC Print more information about the heap before and after each collection. Default: - (disabled).
どうやって気づいたかというと、適当なシステムプロパティを設定したら怒られたので、それでわかりました…。
$ ./print-args -Dgraal.foo=bar error: Could not find option 'foo'. Use -Dgraal.PrintFlags= to list all available options.
ちゃんと見ると、いろいろわかるものですねぇ。