ネイティブイメージのビルド出力

ここでは、GraalVM Native Image のビルド出力に関する情報をご覧いただけます。以下は、`HelloWorld` クラスのネイティブ実行ファイルをビルドする際の出力例です。

================================================================================
GraalVM Native Image: Generating 'helloworld' (executable)...
================================================================================
[1/8] Initializing...                                            (2.8s @ 0.15GB)
 Java version: 20+34, vendor version: GraalVM CE 20-dev+34.1
 Graal compiler: optimization level: 2, target machine: x86-64-v3
 C compiler: gcc (linux, x86_64, 12.2.0)
 Garbage collector: Serial GC (max heap size: 80% of RAM)
--------------------------------------------------------------------------------
 Build resources:
 - 13.24GB of memory (42.7% of 31.00GB system memory, determined at start)
 - 16 thread(s) (100.0% of 16 available processor(s), determined at start)
[2/8] Performing analysis...  [****]                             (4.5s @ 0.54GB)
    3,163 reachable types   (72.5% of    4,364 total)
    3,801 reachable fields  (50.3% of    7,553 total)
   15,183 reachable methods (45.5% of   33,405 total)
      957 types,    81 fields, and   480 methods registered for reflection
       57 types,    55 fields, and    52 methods registered for JNI access
        4 native libraries: dl, pthread, rt, z
[3/8] Building universe...                                       (0.8s @ 0.99GB)
[4/8] Parsing methods...      [*]                                (0.6s @ 0.75GB)
[5/8] Inlining methods...     [***]                              (0.3s @ 0.32GB)
[6/8] Compiling methods...    [**]                               (3.7s @ 0.60GB)
[7/8] Laying out methods...   [*]                                (0.8s @ 0.83GB)
[8/8] Creating image...       [**]                               (3.1s @ 0.58GB)
   5.32MB (24.22%) for code area:     8,702 compilation units
   7.03MB (32.02%) for image heap:   93,301 objects and 5 resources
   8.96MB (40.83%) for debug info generated in 1.0s
 659.13kB ( 2.93%) for other data
  21.96MB in total
--------------------------------------------------------------------------------
Top 10 origins of code area:            Top 10 object types in image heap:
   4.03MB java.base                        1.14MB byte[] for code metadata
 927.05kB svm.jar (Native Image)         927.31kB java.lang.String
 111.71kB java.logging                   839.68kB byte[] for general heap data
  63.38kB org.graalvm.nativeimage.base   736.91kB java.lang.Class
  47.59kB jdk.proxy1                     713.13kB byte[] for java.lang.String
  35.85kB jdk.proxy3                     272.85kB c.o.s.c.h.DynamicHubCompanion
  27.06kB jdk.internal.vm.ci             250.83kB java.util.HashMap$Node
  23.44kB org.graalvm.sdk                196.52kB java.lang.Object[]
  11.42kB jdk.proxy2                     182.77kB java.lang.String[]
   8.07kB jdk.graal.compiler             154.26kB byte[] for embedded resources
   1.39kB for 2 more packages              1.38MB for 884 more object types
--------------------------------------------------------------------------------
Recommendations:
 HEAP: Set max heap for improved and more predictable memory usage.
 CPU:  Enable more CPU features with '-march=native' for improved performance.
--------------------------------------------------------------------------------
    0.8s (4.6% of total time) in 35 GCs | Peak RSS: 1.93GB | CPU load: 9.61
--------------------------------------------------------------------------------
Build artifacts:
 /home/janedoe/helloworld/helloworld (executable)
 /home/janedoe/helloworld/helloworld.debug (debug_info)
 /home/janedoe/helloworld/sources (debug_info)
================================================================================
Finished generating 'helloworld' in 17.0s.

ビルドステージ #

初期化 #

このステージでは、Native Image のビルドプロセスがセットアップされ、`Feature` が初期化されます。

Native Imageの種類

デフォルトでは、Native Image は*実行ファイル*を生成しますが、*ネイティブ共有ライブラリ**静的実行ファイル*も生成できます。

Java バージョン情報

Native Image プロセスの Java とベンダーのバージョン。どちらも、生成されたネイティブバイナリ内の `java.vm.version` および `java.vendor.version` プロパティに使用されます。問題を報告する際には、バージョンとベンダーを報告してください。

Graalコンパイラ

Graal コンパイラで使用される、選択された最適化レベルとターゲットマシンタイプ。最適化レベルは `-O` オプションで制御でき、デフォルトは `2` で、積極的な最適化が有効になります。`-Ob` を使用すると、高速ビルドモードが有効になり、コンパイルステージが高速化されます。これは、開発中にイメージのビルド時間を短縮するのに役立ちます。`-Os` を使用すると、サイズが最適化されます。ターゲットマシンタイプは `-march` オプションで選択でき、AMD64 ではデフォルトで `x86-64-v3`、AArch64 では `armv8-a` になります。このオプションの使用方法に関する推奨事項については、こちらをご覧ください。

Oracle GraalVM では、この行には プロファイルに基づく最適化 (PGO) に関する情報も表示されます。

  • `off`:PGO は使用されません
  • `instrument`:生成された実行ファイルまたは共有ライブラリは、PGO のデータを収集するためにインストゥルメントされます(`--pgo-instrument`)
  • `user-provided`:PGO が有効になっており、ユーザーが提供したプロファイルを使用します(例:`--pgo default.iprof`)
  • `ML-inferred`:機械学習 (ML) モデルを使用して、制御分割ブランチのプロファイルを静的に推測します。

Cコンパイラ

Native Image ビルドプロセスで使用される C コンパイラの実行ファイル、ベンダー、ターゲットアーキテクチャ、およびバージョン情報。

ガベージコレクタ

生成された実行ファイル内で使用されるガベージコレクタ

  • *シリアル GC* はデフォルトの GC で、メモリフットプリントが小さく、Java ヒープサイズが小さい場合に最適化されています。
  • *G1 GC* (GraalVM Community Edition では使用不可) は、Stop-the-World の一時停止を削減し、高スループットを達成しながらレイテンシを向上させるために最適化されたマルチスレッド GC です。
  • *Epsilon GC* はガベージコレクションを実行せず、少量のメモリのみを割り当てる非常に短時間実行のアプリケーション向けに設計されています。

詳細については、メモリ管理に関するドキュメントを参照してください。

最大ヒープサイズ

デフォルトでは、ヒープサイズはシステムメモリの一定の割合に制限されており、ガベージコレクタはポリシーに従って自由にメモリを割り当てることができます。ネイティブ実行ファイルを起動する際に `-Xmx` オプションを使用します(例:64MB の場合は `./myapp -Xmx64m`)メモリフットプリントを低く、より予測可能なものにするために、最大ヒープサイズを制限します。これは場合によってはレイテンシを向上させることもできます。Native Image でビルドする際に `-R:MaxHeapSize` オプションを使用して、最大ヒープサイズを事前に設定します。

ユーザー固有の機能

ユーザーによって提供または明示的に有効化された、あるいはフレームワークなどによって暗黙的にユーザーのために登録されたすべての `Feature`。GraalVM Native Image は、このリストから除外される多くの内部機能をデプロイします。

実験的オプション

すべてのアクティブな実験的オプションのリスト。その起源と、可能な場合は代替 API オプションが含まれます。

本番環境では実験的オプションの使用は避けるべきであり、いかなるリリースでも変更される可能性があります。実験的な機能に依存しており、オプションを安定したものにしたい場合は、問題を報告してください。

取得された `NATIVE_IMAGE_OPTIONS`

`NATIVE_IMAGE_OPTIONS` 環境変数によって取得された追加のビルドオプション。`JAVA_TOOL_OPTIONS` と同様に、環境変数の値は `native-image` に提供されるオプションの前に付加されます。引数ファイルは `NATIVE_IMAGE_OPTIONS` を介して渡すことはできません。`NATIVE_IMAGE_OPTIONS` 環境変数は、ユーザー、ビルド環境、またはツールが追加のビルドオプションを挿入するために使用されるように設計されています。

ビルドリソース

ビルドプロセスで使用されるメモリ制限とスレッド数。

より正確には、Java ヒープのメモリ制限であるため、実際のメモリ消費量はさらに高くなる可能性があります。ビルドの最後に報告される ピーク RSS を確認して、実際に使用されたメモリの量を把握してください。デフォルトでは、ビルドプロセスは空きメモリのみを使用しようとします (ビルドマシンのメモリ負荷を回避するため)。また、32GB を超えるメモリを使用することはありません。8GB 未満の空きメモリしかない場合、ビルドプロセスは合計メモリの 85% を使用するようにフォールバックします。したがって、マシンがビルド中に遅い場合は、不要なアプリケーションを閉じてメモリを解放することを検討してください。`-J-XX:MaxRAMPercentage=60.0` や `-J-Xmx16g` などでデフォルトの動作を上書きすることが可能です。

デフォルトでは、ビルドプロセスは速度を最大化するために使用可能なすべてのプロセッサを使用しますが、32 スレッドを超えることはありません。`--parallelism` オプションを使用して、スレッド数を明示的に設定します (例:`--parallelism=4`)。システムの負荷とメモリ消費量を削減するために、より少ないスレッドを使用します (ビルドプロセスの速度が低下します)。

分析の実行 #

このステージでは、ポイントツー分析 が実行されます。進行状況インジケータは、分析の反復回数を視覚化します。反復回数が多ければ、設定ミスや機能の誤動作が原因で分析に問題が発生している可能性があります。

到達可能な型、フィールド、およびメソッド

ビルドプロセスの一部としてロードされた型、フィールド、およびメソッドの総数に対する、到達可能な型 (プリミティブ、クラス、インターフェース、および配列)、フィールド、およびメソッドの数。到達できないロードされた要素の数が非常に多い場合は、設定に問題がある可能性があります。オーバーヘッドを削減するには、クラスパスとモジュールパスにアプリケーションのビルドに必要なエントリのみが含まれていることを確認してください。

リフレクション登録

リフレクション用に登録されている型、フィールド、およびメソッドの数。数が多くなると、リフレクションのオーバーヘッドが大きくなり、ビルドプロセスが遅くなり、ネイティブバイナリのサイズが大きくなる可能性があります (リフレクションメタデータ を参照)。

JNI アクセス登録

JNI アクセス用に登録されている型、フィールド、およびメソッドの数。

外部関数スタブ

外部関数アクセス用に登録されているダウンコールとアップコールの数。

ランタイムコンパイルメソッド

ランタイムコンパイル用にマークされたメソッドの数。この数は、たとえば Truffle 言語をビルドする場合など、ランタイムコンパイルが実行ファイルに組み込まれている場合にのみ表示されます。ランタイムコンパイルされたメソッドは、ヒープ内の グラフエンコーディング を占めます。

ユニバースの構築 #

このステージでは、すべての型、フィールド、およびメソッドを含むユニバースが構築され、ネイティブバイナリの作成に使用されます。

メソッドの解析 #

このステージでは、Graal コンパイラは到達可能なすべてのメソッドを解析します。進行状況インジケータは、増加する間隔で定期的に出力されます。

メソッドのインライン化 #

このステージでは、簡単なメソッドのインライン化が実行されます。進行状況インジケータは、インライン化の反復回数を視覚化します。

メソッドのコンパイル #

このステージでは、Graal コンパイラは到達可能なすべてのメソッドをマシンコードにコンパイルします。進行状況インジケータは、増加する間隔で定期的に出力されます。

メソッドのレイアウト #

このステージでは、コンパイルされたメソッドがレイアウトされます。進行状況インジケータは、増加する間隔で定期的に出力されます。

イメージの作成 #

このステージでは、ネイティブバイナリが作成され、ディスクに書き込まれます。デバッグ情報も (要求された場合) このステージの一部として生成されます。

コード領域

コード領域には、到達可能なすべてのメソッドに対して Graal コンパイラによって生成されたマシンコードが含まれています。したがって、到達可能なメソッドの数を減らすと、コード領域のサイズも削減されます。

コード領域の起源

ユーザーがコード領域のマシンコードの出所を理解するのに役立つように、ビルド出力には、主要な起源の内訳が表示されます。起源とは、Javaソースのグループであり、利用可能な情報に応じて、JARファイル、パッケージ名、またはクラス名になります。たとえば、java.baseモジュールには、JDKの基本クラスが含まれています。svm.jarファイル、org.graalvm.nativeimage.baseモジュール、および類似の起源には、Native Imageランタイムの内部ソースが含まれています。コード領域のサイズ、ひいてはネイティブ実行可能ファイルの合計サイズを削減するには、コード領域の内訳に基づいてアプリケーションの依存関係を再評価します。一部のライブラリとフレームワークは、他のライブラリやフレームワークよりもNative Imageの準備が整っており、ライブラリやフレームワークの新しいバージョンでは、コードフットプリントが改善(または悪化)する可能性があります。

イメージヒープ

ヒープには、静的アプリケーションデータ、メタデータ、およびさまざまな目的のためのbyte[]などの到達可能なオブジェクトが含まれています(以下を参照)。

byte[]に格納される一般的なヒープデータ

java.lang.Stringコードメタデータリフレクションメタデータ、またはグラフエンコーディングに使用されていないすべてのbyte[]オブジェクトの合計サイズ。したがって、これにはアプリケーションコードからのbyte[]オブジェクトも含まれる可能性があります。

byte[]に格納される埋め込みリソース

ネイティブバイナリ内にリソース(たとえば、Class.getResource()を介してアクセスされるファイル)を格納するために使用されるすべてのbyte[]オブジェクトの合計サイズ。リソースの数は、ヒープセクションに表示されます。モジュール、名前、起源、サイズなどの追加情報を含むすべてのリソースのリストは、ビルドレポートに含まれています。この情報は、-H:+GenerateEmbeddedResourcesFileオプションを使用してJSON形式で要求することもできます。このようなJSONファイルは、embedded-resources-schema-v1.0.0.jsonで定義されているJSONスキーマに対して検証されます。

byte[]に格納されるコードメタデータ

コード領域のメタデータに使用されるすべてのbyte[]オブジェクトの合計サイズ。したがって、到達可能なメソッドの数を減らすと、このメタデータのサイズも削減されます。

byte[]に格納されるリフレクションメタデータ

型、フィールド、メソッド、コンストラクタデータを含む、リフレクションメタデータに使用されるすべてのbyte[]オブジェクトの合計サイズ。リフレクションメタデータの量を減らすには、リフレクションに登録されている要素の数を減らします。

byte[]に格納されるグラフエンコーディング

グラフエンコーディングに使用されるすべてのbyte[]オブジェクトの合計サイズ。これらのエンコーディングは、ランタイムでコンパイルされたメソッドの結果です。したがって、そのようなメソッドの数を減らすと、対応するグラフエンコーディングのサイズも削減されます。

ヒープアラインメント

選択されたガベージコレクタ用にヒープを調整するために予約された追加スペース。ヒープアラインメントには、GC固有のデータ構造も含まれる場合があります。したがって、そのサイズは、異なるガベージコレクタに切り替えることによってのみ影響を受ける可能性があります。

デバッグ情報

生成されたデバッグ情報の合計サイズ(有効な場合)。

その他のデータ

コード領域ヒープデバッグ情報のいずれにもない、バイナリ内のデータ量。このデータには、通常、Native Imageの内部情報が含まれており、支配的であってはなりません。

セキュリティレポート #

このセクションは、GraalVM Community Editionでは使用できません。

デシリアライゼーション

これは、Javaデシリアライゼーションがネイティブ実行可能ファイルに含まれているかどうかを示します。含まれていない場合、実行可能ファイルはJavaデシリアライゼーションに基づく攻撃で悪用できないため、実行可能ファイルの攻撃対象領域が削減されます。

ソフトウェア部品表(SBOM)

このセクションは、SBOMが組み立てられたかどうか、およびどのような方法で格納されたかを示します。ストレージ形式には、SBOMをバイナリに埋め込む`embed`、SBOMをクラスパスに保存する`classpath`、SBOMをJSONビルドアーチファクトとして含める`export`が含まれます。 `--enable-sbom`を使用して、デフォルトで`embed`オプションであるこの機能をアクティブにします。埋め込まれている場合、SBOMサイズが表示されます。コンポーネントの数は常に表示されます。

詳細については、ソフトウェア部品表を参照してください。

逆エッジ制御フロー整合性(CFI)

制御フロー整合性(CFI)は、実験的な`-H:CFI=HW`オプションで適用できます。この機能は現在、Linux AArch64用にGraalによってコンパイルされたコードでのみ使用可能であり、ポインター認証コード(PAC)を活用して関数のリターンアドレスの整合性を確保します。

ソフトウェア制御フロー整合性(CFI)

制御フロー整合性(CFI)は、実験的な`-H:CFI=SW_NONATIVE`オプションを使用してソフトウェアで適用できます。この機能は現在、Linux AMD64用にGraalによってコンパイルされたコードでのみ使用可能であり、間接分岐とメソッド戻りのターゲットを検証します。

推奨事項 #

ビルド出力には、Native Imageを最大限に活用するのに役立つ、以下の推奨事項が1つ以上含まれている場合があります。

AWT:Abstract Window Toolkitの到達可能性メタデータがありません

Native Image分析には、java.awtパッケージのクラスが含まれていますが、到達可能性メタデータが見つかりませんでした。トレースエージェントを使用して、アプリケーションのメタデータを収集します。そうでない場合、アプリケーションは正しく動作しない可能性があります。アプリケーションがデスクトップアプリケーションではない場合(たとえば、SwingまたはAWTを直接使用している場合)、AWTへの依存関係が実際に必要かどうかを再評価することをお勧めします。

CPU:パフォーマンス向上のため、より多くのCPU機能を有効にします

Native Imageビルドプロセスでは、CPUが現在有効になっているよりも多くの機能(AESやLSEなど)をサポートしていることが判明しました。アプリケーションを同じマシンまたは同じCPU機能をサポートする類似のマシンにデプロイする場合は、ビルド時に`-march=native`を使用することを検討してください。このオプションを使用すると、Graalコンパイラは利用可能なすべてのCPU機能を使用できるため、アプリケーションのパフォーマンスが大幅に向上する可能性があります。`-march=list`を使用して、明示的にターゲットにすることができるすべての使用可能なマシンの種類を一覧表示します。

G1GC:レイテンシとスループットを向上させるためにG1ガベージコレクタを使用します

G1ガベージコレクタは、プラットフォームで使用できます。ビルド時に`--gc=G1`を使用して有効にすることで、アプリケーションのレイテンシとスループットを向上させることができます。詳細については、メモリ管理に関するドキュメントを参照してください。ピークパフォーマンスを最大限に高めるには、プロファイルガイダンス付き最適化の使用も検討してください。

HEAP:最大ヒープサイズを指定します

最大ヒープサイズを参照してください。

PGO:スループットを向上させるためにプロファイルガイダンス付き最適化を使用します

プロファイルガイダンス付き最適化を使用して、スループットを向上させるためにアプリケーションを最適化することを検討してください。これらの最適化により、Graalコンパイラは、アプリケーションをAOTコンパイルするときに、JITコンパイラとして実行されている場合と同様に、プロファイリング情報を利用できます。このためには、次の手順を実行します

  1. `--pgo-instrument`を使用してアプリケーションをビルドします。
  2. 代表的なワークロードでインストルメント化されたアプリケーションを実行して、`.iprof`ファイルの形式でプロファイリング情報を生成します。
  3. アプリケーションを再構築し、`--pgo=<your>.iprof`でプロファイリング情報を渡して、アプリケーションの最適化バージョンを生成します。

関連ガイド:プロファイルガイダンス付き最適化を使用してネイティブ実行可能ファイルを最適化する

ピークパフォーマンスを最大限に高めるには、G1ガベージコレクタの使用も検討してください。

`QBM`:高速ビルドのためにクイックビルドモードを使用します

開発中は、クイックビルドモード( `-Ob`)を使用してビルドを高速化することを検討してください。より正確には、このモードはGraalコンパイラによって実行される最適化の数を減らし、コンパイルステージの全体的な時間を短縮します。クイックビルドモードは開発に役立つだけでなく、生成される実行可能ファイルのサイズを小さくすることもできます。ただし、最適化の数が減少するため、実行可能ファイルの全体的なピークスループットが低下する可能性があることに注意してください。

INIT: 厳密なイメージヒープ構成を使用する

構成量を削減し、これがデフォルトになる将来の GraalVM リリースに備えるために、`--strict-image-heap` の使用を開始します。このモードでは、イメージヒープに格納されているクラスのみを `--initialize-at-build-time` でマークする必要があります。これにより、ビルド時の初期化を実現するために必要な構成エントリの数が効果的に削減されます。新しいモードを採用する際には、ビルド時の初期化を最初から導入するのが最善です。このプロセス中は、ビルド時の初期化のために、パッケージ全体ではなく個々のクラスを選択するのが最善です。また、新しいフラグに移行する前に、フレームワークの依存関係をすべて最新バージョンに更新してください。フレームワークも移行が必要になる場合があります。

JDK 22 用 GraalVM 以降の Native Image では、`--strict-image-heap` がデフォルトで有効になっていることに注意してください。

リソース使用状況統計 #

ガベージコレクション

すべてのガベージコレクタで費やされた合計時間、合計GC時間 / 総プロセス時間(パーセント)、およびガベージコレクションの総数。多数のコレクションまたはコレクタで費やされた時間は、通常、システムがメモリ不足になっていることを示しています。ネイティブバイナリをビルドする時間を短縮するには、使用可能なメモリの量を増やします。

ピークRSS

OS が報告するピーク 常駐セットサイズ(RSS)。この値は、ビルドプロセスによって消費されるメモリの最大量を示します。ビルドリソースセクションで報告されているメモリ制限とこの値を比較することをお勧めします。十分なヘッドルームがあり、GC統計に問題がない場合は、システムの総メモリ量をピークRSSに近い値に減らして運用コストを削減できます。

CPU負荷

プロセスで使用されたCPU時間とプロセス時間の合計の比率です。ネイティブバイナリのビルド時間を短縮するには、CPUコア数を増やしてください。

ビルドアーティファクト #

すべてのビルドアーティファクトのリスト。これには、生成されたネイティブバイナリが含まれますが、追加のライブラリ、Cヘッダーファイル、デバッグ情報などの他のアーティファクトも含まれる場合があります。これらのアーティファクトの一部は、実行時に必要となるため、ネイティブバイナリと同じ場所に配置する必要があります。たとえば、AWTを使用するアプリケーションの場合、ビルドプロセスではJDKのライブラリと互換性のあるAWTサポートを提供するためのshimも出力されます。これらのライブラリは、ネイティブバイナリと一緒にコピーおよび配布する必要があります。ビルドアーティファクトリストの機械可読バージョンをJSON形式で生成するようにビルダーに指示するには、-H:+GenerateBuildArtifactsFileオプションを使用します。このようなJSONファイルは、build-artifacts-schema-v0.9.0.jsonで定義されているJSONスキーマに対して検証されます。このスキーマには、考えられる各アーティファクトタイプの説明と、実行時に必要かどうかについても説明が含まれています。

機械可読ビルド出力 #

native-imageビルダーによって生成されるビルド出力は、人間が理解できるように設計されており、新しいリリースで進化する可能性があるため、ツールによって解析されるべきではありません。代わりに、-H:BuildOutputJSONFile=<file.json>オプションを使用して、ビルダーに、たとえば監視ツールを構築するために使用できるJSON形式の機械可読ビルド出力を生成するように指示します。このようなJSONファイルは、build-output-schema-v0.9.3.jsonで定義されているJSONスキーマに対して検証されます。JSONファイルは、ビルドが成功した場合にのみ生成されることに注意してください。

次の例は、CI/CDビルドパイプラインで到達可能なメソッドの数が特定のしきい値を超えないことを確認するために、これを使用する方法を示しています。

native-image -H:BuildOutputJSONFile=build.json HelloWorld
# ...
cat build.json | python3 -c "import json,sys;c = json.load(sys.stdin)['analysis_results']['methods']['reachable']; assert c < 12000, f'Too many reachable methods: {c}'"
Traceback (most recent call last):
  File "<string>", line 1, in <module>
AssertionError: Too many reachable methods: 12128

カラフルなビルド出力 #

デフォルトでは、native-imageビルダーは、適切なターミナルが見つかった場合、読みやすくするためにビルド出力を色付けします。また、カラーサポートを確認する際に、NO_COLORCI、およびTERM環境変数も考慮します。カラフルな出力を明示的に制御するには、--colorオプションをalwaysnever、またはauto(デフォルト)に設定します。

お問い合わせ