Ahead-of-time (AOT) caching

このガイドでは、Quarkus において OpenJDK の Ahead-of-Time (AOT) キャッシング機能を活用し、アプリケーションの起動時間を大幅に短縮する方法について説明します。

概要

JDK 24 以降、 Project Leyden により、Java アプリケーションの起動時間を大幅に短縮できる強力な AOT キャッシング機能 (JEP 483) が導入されました。 Quarkus はこれらの機能をファーストクラスでサポートしており、AOT 最適化されたアプリケーションのビルドとデプロイを容易にします。

Leyden AOT には JDK 24 以降 が必要です。それより古い JDK バージョンの場合、Quarkus は AppCDS にフォールバックできます (AppCDS (レガシー) を参照)。

クイックスタート

AOT キャッシングを有効にして Quarkus アプリケーションをビルドするには、以下のようにします。

Maven
./mvnw verify -Dquarkus.package.jar.aot.enabled=true -DskipITs=false (1)
1 ツールによって生成されたプロジェクトを使用している場合、 -DskipITs=false を追加することで統合テストが確実に実行されるようになります。
Gradle
./gradlew build quarkusIntTest -Dquarkus.package.jar.aot.enabled=true
When enabling AOT via quarkus.package.jar.aot.enabled=true, Quarkus will automatically switch to the aot-jar JAR packaging if none is explicitly configured via quarkus.package.jar.type.

その後、次のコマンドでアプリケーションを実行します。

Maven
cd target/quarkus-app
java -XX:AOTCache=app.aot -jar quarkus-run.jar
Gradle
cd build/quarkus-app
java -XX:AOTCache=app.aot -jar quarkus-run.jar

AOT 最適化された JAR パッケージング

Quarkus は、OpenJDK の AOT 機能と最適に動作するように設計された、専用の aot-jar パッケージングタイプを提供します。このパッケージングタイプは以下の特徴を持ちます。

  • 最適な AOT クラスロードのためにアプリケーションを構成する

  • すべてのクラスロードを JDK のクラスローダーに委譲する (Leyden が現在カスタムクラスローダーをサポートしていないため、AOT を効果的に機能させるために必要です)

  • 実行時のクラスパススキャンを避けるため、頻繁にアクセスされるリソース (サービスローダーファイルなど) をキャッシュする

It is not recommended to use the aot-jar packaging outside of the AOT use case, as the fast-jar packaging offers more optimizations that result in better performance compared to the aot-jar when Leyden’s AOT cache is not used.

AOT キャッシュの生成

AOT キャッシュの生成を有効にするには、以下のようにします。

Maven
./mvnw package -Dquarkus.package.jar.aot.enabled=true
Gradle
./gradle build -Dquarkus.package.jar.aot.enabled=true

JDK 24 以降では、これにより Maven の場合は target/quarkus-app/ に、Gradle の場合は build/quarkus-app/ に app.aot ファイルが生成されます。

統合テストによるトレーニング

最適な結果を得るには、実際のアプリケーションワークロードを実行して AOT キャッシュを「トレーニング」する必要があります。 Quarkus は、このトレーニングに @QuarkusIntegrationTest テストスイートを使用できます。

Maven
./mvnw verify -Dquarkus.package.jar.aot.enabled=true -DskipITs=false (1)
1 ツールによって生成されたプロジェクトを使用している場合、 -DskipITs=false を追加することで統合テストが確実に実行されるようになります。
Gradle
./gradlew build quarkusIntTest -Dquarkus.package.jar.aot.enabled=true

このアプローチでは、以下のようになります。

  1. Quarkus がアプリケーションをビルドする

  2. AOT トレーニングが有効な状態で、アプリケーションに対して統合テスト (つまり @QuarkusIntegrationTest アノテーションが付いたテスト) が実行される

  3. JVM がテスト実行中にプロファイリングデータを取得する

  4. 最適化された app.aot キャッシュが生成される

統合テストが本番のトラフィックをより忠実に再現しているほど、AOT キャッシュはより効果的になります。

このアプローチを機能させるには、統合テストをスキップしてはいけません。

ツールで生成された Maven プロジェクトでは、統合テストはデフォルトで無効になっており、ネイティブビルドの時のみ実行されます。 -DskipITs=false を指定して有効にしてください。

トレーニングフェーズの制御

quarkus.package.jar.aot.phase 設定プロパティーでトレーニングが行われるタイミングを制御します。

  • auto (デフォルト): Leyden AOT のために integration-tests を使用します

  • build: ビルド中にキャッシュを生成します (トレーニングは非常に限定的ですが、ビルドは速くなります)

  • integration-tests: 統合テストの実行中に生成します (より高度な最適化)。Leyden AOT の場合、これは auto と同じ効果を持ちます。

Maven
# Explicit integration test training
./mvnw verify -Dquarkus.package.jar.aot.enabled=true -Dquarkus.package.jar.aot.phase=integration-tests

# Build-time only (builds faster, less optimal)
./mvnw package -Dquarkus.package.jar.aot.enabled=true -Dquarkus.package.jar.aot.phase=build
Gradle
# Explicit integration test training
./mvnw build quarkusIntTest -Dquarkus.package.jar.aot.enabled=true -Dquarkus.package.jar.aot.phase=integration-tests

# Build-time only (builds faster, less optimal)
./mvnw build -Dquarkus.package.jar.aot.enabled=true -Dquarkus.package.jar.aot.phase=build

AOT キャッシュでの実行

-XX:AOTCache JVM フラグを使用してアプリケーションを起動します。

Maven
cd target/quarkus-app
java -XX:AOTCache=app.aot -jar quarkus-run.jar
Gradle
cd build/quarkus-app
java -XX:AOTCache=app.aot -jar quarkus-run.jar

-Xlog:aot オプションを使用すると、AOT キャッシュの使用状況に関する詳細情報を取得できます。

-Xlog:class+load=info,aot+codecache=debug:file=aot.log:level,tags を使用すると、 aot.log ファイルにさらに詳細な情報を収集できます。

Options that add modules, such as Flight Recorder

The JVM only uses an AOT cache if the application runs with the same --add-modules as the training run. Otherwise it reports an error such as the following and starts the application without the cache:

[error][aot] Mismatched values for property jdk.module.addmods: jdk.jfr specified during runtime but not during dump time

Some JVM options add a module implicitly. The most common one is -XX:StartFlightRecording, which adds jdk.jfr; enabling the Vector API with --add-modules=jdk.incubator.vector has the same effect.

If the application is always started with such an option, pass the corresponding --add-modules to the training run with quarkus.package.jar.aot.additional-recording-args:

Maven
./mvnw verify -Dquarkus.package.jar.aot.enabled=true -Dquarkus.package.jar.aot.additional-recording-args=--add-modules=jdk.jfr
Gradle
./gradlew build quarkusIntTest -Dquarkus.package.jar.aot.enabled=true -Dquarkus.package.jar.aot.additional-recording-args=--add-modules=jdk.jfr

The check works both ways: a cache generated this way is only used when the application is started with -XX:StartFlightRecording or --add-modules=jdk.jfr, and is rejected otherwise. A single cache cannot serve both kinds of runs.

To record only occasionally, keep the default cache and start the recording on the running application instead, which does not affect the cache:

jcmd <pid> JFR.start

手動による AOT ファイル生成

上述の通り、AOT ファイルの生成に関しては Quarkus がすべての面倒な作業を引き受けます。ただし、より細かな制御が必要な場合は、ユーザーが必要な手順を手動で実行することもできます。

aot-jar パッケージングを使用してアプリケーションをビルドするには、以下を使用します。

Maven
mvn package -Dquarkus.package.jar.type=aot-jar
Gradle
./gradlew build -Dquarkus.package.jar.type=aot-jar

レコーディングモードでアプリケーションを起動するには、以下を使用します。

Maven
cd target/quarkus-app
java -XX:AOTCacheOutput=app.aot -jar quarkus-run.jar
Gradle
cd build/quarkus-app
java -XX:AOTCacheOutput=app.aot-jar quarkus-run.jar

アプリケーションに負荷をかけた後、停止させます。プロセスが停止すると、 quarkus-run.jar と同じディレクトリーに app.aot が作成されていることがわかります。

詳細は [JEP 514](https://openjdk.org/jeps/514) を参照してください。

IBM Semeru

Quarkus also supports Semeru’s [Class Data Sharing](https://www.ibm.com/docs/en/semeru-runtime-ce-z/21.0.0?topic=sharing-introduction) AOT features.

AOT キャッシングを有効にして Quarkus アプリケーションをビルドするには、以下のようにします。

Maven
./mvnw verify -Dquarkus.package.jar.aot.enabled=true -DskipITs=false (1)
1 ツールによって生成されたプロジェクトを使用している場合、 -DskipITs=false を追加することで統合テストが確実に実行されるようになります。
Gradle
./gradlew build quarkusIntTest -Dquarkus.package.jar.aot.enabled=true

When the JVM building the application and running the tests is IBM Semeru, then Quarkus will generate a shared classes cache instead of a Leyden AOT file.

その後、次のコマンドでアプリケーションを実行します。

Maven
cd target/quarkus-app
java -Xshareclasses:name=quarkus-app,cacheDir=app-scc,readonly -jar quarkus-run.jar
Gradle
cd build/quarkus-app
java  -Xshareclasses:name=quarkus-app,cacheDir=app-scc,readonly -jar quarkus-run.jar

コンテナイメージ

Quarkus は AOT キャッシュを含むコンテナーイメージを自動的にビルドできるため、すぐに高速な起動時間の恩恵を受けることができます。

AOT 強化されたコンテナーイメージのビルド

quarkus-container-image-jib 、 quarkus-container-image-docker 、または quarkus-container-image-podman を使用する場合。

Maven
./mvnw verify -Dquarkus.package.jar.aot.enabled=true -Dquarkus.container-image.build=true -DskipITs=false (1)
1 ツールによって生成されたプロジェクトを使用している場合、 -DskipITs=false を追加することで統合テストが確実に実行されるようになります。
Gradle
./gradlew build quarkusIntTest buildAotEnhancedImage -Dquarkus.package.jar.aot.enabled=true -Dquarkus.container-image.build=true

これにより、以下のことが行われます。

  1. aot-jar パッケージングでアプリケーションをビルドする

  2. ベースとなるコンテナーイメージを作成する

  3. AOT キャッシュをトレーニングするために統合テストを実行する

  4. AOT キャッシュを含み、それを使用するように事前設定された、イメージバージョンに -aot サフィックスが付いた新しいコンテナーイメージを作成する

コンテナーイメージエクステンションの追加

プロジェクトに以下の依存関係のいずれかを追加します。

pom.xml
<!-- Jib (recommended for most use cases) -->
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-container-image-jib</artifactId>
</dependency>

<!-- Or Docker -->
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-container-image-docker</artifactId>
</dependency>

<!-- Or Podman -->
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-container-image-podman</artifactId>
</dependency>
build.gradle
// Jib (recommended for most use cases)
implementation("io.quarkus:quarkus-container-image-jib")

// Or Docker
implementation("io.quarkus:quarkus-container-image-docker")

// Or Podman
implementation("io.quarkus:quarkus-container-image-podman")

要件と制限事項

  • Leyden AOT 機能には JDK 24 以降 が必要です

  • AOT キャッシュは JDK バージョン固有 です。実行時には、キャッシュの生成に使用されたものと全く同じ JDK バージョンを使用する必要があります。

  • この機能は Windows 環境ではテストされていません

設定リファレンス

ビルド時に固定される設定プロパティ - それ以外の設定プロパティは実行時に上書き可能

Configuration property

タイプ

デフォルト

Whether to automate the creation of an AOT file.

Environment variable: QUARKUS_PACKAGE_JAR_AOT_ENABLED

Show more

boolean

false

The type of AOT file to generate

If auto is used, Quarkus will generate an AOT file on OpenJDK 25+, an SCC on IBM Semeru, and an AppCDS file otherwise.

Environment variable: QUARKUS_PACKAGE_JAR_AOT_TYPE

Show more

auto, aot, app-cds, scc

Comma-separated list of additional recording arguments passed to the recording command line.

For instance, may be used to enable advanced logging with: -Xlog:aot+map=trace,aot+map+oops=trace,aot=warning:file=aot-analysis.map:none:filesize=0 -Xlog:aot+resolve*=trace,aot+codecache+exit=debug:file=training.log:level,tags

If an argument includes the , symbol, it needs to be escaped, e.g. \\,

Environment variable: QUARKUS_PACKAGE_JAR_AOT_ADDITIONAL_RECORDING_ARGS

Show more

文字列のリスト

The phase in which the AOT file should be generated.

For Leyden AOT, auto means integration-tests.

For AppCDS and SCC, auto means build (and an error will be thrown if AppCDS is set to integration-tests).

Environment variable: QUARKUS_PACKAGE_JAR_AOT_PHASE

Show more

auto, build, integration-tests

AppCDS (レガシー)

JDK 24 未満のバージョンでは、Quarkus はフォールバックとして Application Class Data Sharing (AppCDS) をサポートしています。 AppCDS による起動の改善は Leyden AOT に比べると控えめですが、古い JDK でも動作します。

AppCDS アーカイブの生成

Maven
./mvnw package -Dquarkus.package.jar.aot.enabled=true -Dquarkus.package.jar.aot.type=app-cds
Gradle
./gradlew build -Dquarkus.package.jar.aot.enabled=true -Dquarkus.package.jar.aot.type=app-cds

これにより app-cds.jsa ファイルが生成されます。

AppCDS での実行

Maven
cd target/quarkus-app
java -XX:SharedArchiveFile=app-cds.jsa -jar quarkus-run.jar
Gradle
cd build/quarkus-app
java -XX:SharedArchiveFile=app-cds.jsa -jar quarkus-run.jar

AppCDS の制限事項

  • JAR とアーカイブへのパスは、ビルド時と実行時で完全に一致している必要があります

  • JDK バージョンは 完全に 同じである必要があります

  • AppCDS はクラスのメタデータのみをキャッシュし、メソッドプロファイルや検証結果はキャッシュしません

  • 統合テスト中のトレーニングは AppCDS ではサポートされていません (ビルド時の生成のみ)