ファイル・サイズのためのネイティブ実行可能ファイルの最適化

様々な最適化レベルを利用して、ネイティブ実行可能ファイルを最適化できます。このガイドでは、サイズの最適化を使用して(-Os)、特定のアプリケーションに対して小さなネイティブ実行可能ファイルを作成する方法を示します。

-Osは、コードまたは実行可能ファイルのサイズを大幅に増加する可能性があるものを除き、-O2の最適化を有効にします。通常は、パフォーマンスの低下と引き換えに、可能なかぎり最小の実行可能ファイルが作成されます。詳細は、「最適化レベル」を参照してください。

前提条件

Oracle GraalVM for JDK 23以降がインストールされていることを確認します。最も簡単に始めるには、SDKMAN!を使用します。その他のインストール・オプションについては、ダウンロード・セクションにアクセスしてください。

デモでは、従来のfortune UNIXプログラムをシミュレートする"fortune teller"アプリケーションを実行します(詳細は、fortuneを参照してください)。

  1. GraalVMデモ・リポジトリをクローニングします。
     git clone https://github.com/graalvm/graalvm-demos.git
    
  2. ディレクトリをfortune-demo/fortune-mavenに変更します:
     cd native-image/native-build-tools/maven-plugin
    

デフォルト構成を使用したネイティブ実行可能ファイルのビルド

  1. ネイティブ・イメージ・ビルド用のMavenプラグインを使用して、ネイティブ実行可能ファイルを作成します:
     ./mvnw -Pnative package
    

    このコマンドは、プロジェクトをコンパイルし、すべての依存関係を含むJARファイルを作成して、targetディレクトリにネイティブ実行可能ファイルfortuneを生成します。

  2. (オプション)アプリケーションを実行します:
     ./target/fortune
    

    アプリケーションはランダムなメッセージを返します。

  3. ファイル・サイズが約13Mであることを確認します:
     du -h target/fortune
    

サイズが最適化されたネイティブ実行可能ファイルのビルド

次に、サイズの最適化をオンにしてネイティブ実行可能ファイルを作成し、以前のビルドと区別するために出力ファイルに別の名前を付けます。

  1. pom.xmlファイルを開きます。native-maven-plugin宣言を検索し、<configuration>要素内で次のビルド引数を確認します:
     <configuration>
         <imageName>fortune-optimized</imageName>
         <buildArgs>
             <buildArg>-Os</buildArg>
             <buildArg>--emit build-report</buildArg>
         </buildArgs>
     </configuration>
    

    -Osオプションは、サイズの最適化を有効にします。オプション--emit build-reportは、targetディレクトリ内の他のアーティファクトとともにビルド・レポートを生成します。

  2. 2番目のネイティブ実行可能ファイルを作成します:
     ./mvnw -Pnative package
    

    このコマンドは、実行可能ファイルfortune-optimizedtargetディレクトリに生成します。

  3. 関連するすべての出力ファイルのサイズを比較します:
     du -h target/fortune*
    

    次のような出力が表示されます:

     13M    target/fortune
     16K    target/fortune-1.0-SNAPSHOT.jar
     9.8M   target/fortune-optimized
     1.9M   target/fortune-optimized-build-report.html
    

    ファイル・サイズが13Mから9.8Mに減少しました。

-Osオプションでファイル・サイズをどの程度減らすことができるかは、アプリケーションごとに異なり、デフォルトの-O2モードでサイズを増やすインライン化および他の最適化をネイティブ・イメージがどの程度適用するかによって変化します。

前のステップで生成されたビルド・レポートfortune-optimized-build-report.htmlは、ネイティブ実行可能ファイルに含まれた内容を正確に示します。これは、通常のWebブラウザで開くことができるHTMLファイルです。

ネイティブ実行可能ファイルのファイル・サイズが非常に大きい場合は、埋込みリソースのリスト、コード領域に含まれるモジュールとパッケージのリスト、またはイメージ・ヒープ内のオブジェクト型のリストを確認して、これらの要素がアプリケーションに不可欠かどうかをチェックできます。到達可能性メタデータのリソース構成に誤った正規表現パターンがあるため、大きなファイルが意図せずリソースとして埋め込まれる場合があります。また、リフレクション用に登録したJava型が間違っているか多すぎると、アプリケーション、ライブラリまたはJDKの不要な部分に偶然アクセスできるようになり、ネイティブ実行可能ファイルのサイズが大幅に増えることがあります。さらに、ビルド時の初期化を特定の目的に使用しないと、空のキャッシュなどの大規模なJavaオブジェクトがイメージ・ヒープに誤って含まれる可能性があり、結果としてネイティブ実行可能ファイルが大きくなります。

一般に、依存関係を追加または更新する場合などに随時ファイル・サイズ、埋込みリソースの数またはその他のメトリックを確認するか、頻繁にビルド・メトリックをモニターすることをお薦めします。このために、マシンによる読取り可能バージョンのビルド出力またはGitHubアクションのビルド・レポートを使用できます。

プロファイルに基づく最適化(PGO)など、他のメトリックの改善に加えて、実行可能ファイルのサイズにプラスの影響を与える可能性のあるその他のネイティブ・イメージ技術もあります。