Amazon Web Services ブログ

AWS SDK for Java 2.xにおけるGraalVM Native Imageのサポート

この記事は2021年2月23日に公開された GraalVM Native Image Support in the AWS SDK for Java 2.x を翻訳したものです。

AWS SDK for Java 2.x (バージョン 2.16.1 以降) で GraalVM Native Imageのコンパイルが標準でサポートされるようになったことをお知らせします。

GraalVMは、JVMベースの言語(例: Java、Scala、Kotlin)、動的型付け言語(例: Python、JavaScript)、LLVMベースの言語(例: C、C++)をサポートする、ユニバーサルな仮想マシンです。

GraalVM Native Imageは、GraalVM が提供する最も人気のある機能の 1 つです。これにより、Java プログラムを、ネイティブイメージと呼ばれる自己完結型の実行可能ファイルに Ahead-of-Time (AoT) コンパイルできます。実行可能ファイルは最適化され、アプリケーションの実行に必要なものがすべて含まれています。また、JVMと比較して起動時間が短縮され、ヒープメモリー・フットプリントも小さくなります。そのためネイティブイメージは、起動時のレイテンシーが重要なサーバーレスアプリケーションに適しています。

私たちは、GraalVM Native Imageから作成した実行可能ファイルと、JVM で実行されている同じアプリケーションの、起動時のパフォーマンスを比較しました。テストアプリケーションは ApacheHttpClient を使用して S3Client を作成し、単純な GetObjectRequest を送信しています。テストでは、AWS SDK for Java 2.x の起動時間、最初のリクエストのレイテンシ、およびメモリ使用量を測定しました。その結果は、ネイティブイメージの起動速度が著しく速く、ヒープメモリー・フットプリントが少ないことを示しています。SDK Startup Latency + First Request Latency(milliseconds)Memory Usage Resident Set Size(MB)

AoT の性質上、クラスの動的読み込み、プロキシ、またはリフレクションに依存する機能は、ビルド時に知っておく必要があり、特別なサポートが必要です。たとえば、リフレクションを使用するクラスは、ネイティブイメージの設定ファイルに登録する必要があります。

最新の AWS SDK for Java 2.x には、SDKクラスに必要な、このような構成が含まれており、ネイティブイメージに組み込むことができます。最新リリース (訳注:この記事は2021年2月23日に公開された GraalVM Native Image Support in the AWS SDK for Java 2.x を翻訳したものです。)には、新しい Maven Archetypeであるarchetype-app-quickstart も含まれています。これにより、AWS SDK for Java 2.x を依存関係として構成された、ネイティブイメージ互換の Java アプリケーションを、迅速に起動することができます。

このブログでは、このarchetypeを使って、GraalVM Native Imageをサポートした新しいアプリケーションを作成する方法を紹介します。

はじめに

前提条件

この記事は、Java プログラミング、Maven ビルドシステム、および GraalVM ランタイムに精通していることを前提としています。このチュートリアルを利用するには、以下のソフトウェアがインストールされている必要があります。

アプリケーションの生成

プロジェクトを生成するには、ターミナル(コマンドライン)ウィンドウを開き、 archetype-app-quickstart を指定して mvn archetype:generate を実行します。archetype のバージョン(archetypeVersion)は、AWS SDK for Java 2.xのバージョンと同じですので、最新のバージョンを使用することが出来ます。実行時に選択できるモードは、以下に示すインタラクティブモードと、バッチモードの 2 つです。

インタラクティブモード

インタラクティブモードでは、以下のコマンドを実行後、必要なプロパティを1つずつ指定するように求められます。

mvn archetype:generate \
  -DarchetypeGroupId=software.amazon.awssdk \
  -DarchetypeArtifactId=archetype-app-quickstart \
  -DarchetypeVersion=2.16.1

バッチモード

バッチモードでは、必要なすべてのプロパティを一度に提供する必要があります。以下は、必要なプロパティのリストです。利用可能なすべてのオプションをここで確認できます

必須のプロパティ
  • service: アプリケーションで使用するサービスクライアントを指定します(例:s3、dynamodb)。 1つのサービスのみを提供する必要があります。
  • groupId: アプリケーションのグループIDを指定します
  • artifactID: アプリケーションのアーティファクトIDを指定します
  • httpClient: SDK クライアントによって使用される HTTP クライアントを指定します。利用可能なオプションは、url-connection-client (sync)、apache-client (sync) 、netty-nio-client (async)です
  • nativeImage: GraalVM Native Image 構成を含めるかどうかを指定します
mvn archetype:generate \
    -DarchetypeGroupId=software.amazon.awssdk \
    -DarchetypeArtifactId=archetype-app-quickstart \
    -DarchetypeVersion=2.16.1 \
    -DgroupId=com.test \
    -DartifactId=sample-project \
    -Dservice=s3  \
    -DhttpClient=apache-client \
    -DnativeImage=true \
    -Dregion=us-west-2 \
    -DinteractiveMode=false

上記のコマンドで生成されるアプリケーションには、AWS SDK for Java 2.16.1 への依存関係があります。出力は次のようになります。

[INFO] ----------------------------------------------------------------------------
[INFO] Using following parameters for creating project from Archetype: archetype-app-quickstart:2.16.1
[INFO] ----------------------------------------------------------------------------
[INFO] Parameter: groupId, Value: com.test
[INFO] Parameter: artifactId, Value: sample-project
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] Parameter: package, Value: com.test
[INFO] Parameter: packageInPathFormat, Value: com/test
[INFO] Parameter: service, Value: s3
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] Parameter: package, Value: com.test
[INFO] Parameter: nativeImage, Value: true
[INFO] Parameter: httpClient, Value: apache-client
[INFO] Parameter: groupId, Value: com.test
[INFO] Parameter: javaSdkVersion, Value: 2.16.1
[INFO] Parameter: artifactId, Value: sample-project
[INFO] Project created from Archetype in dir: /tmp/sample-project
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  4.004 s
[INFO] Finished at: 2021-02-17T15:07:45-08:00
[INFO] ------------------------------------------------------------------------

archetype:generateのゴールが完了すると、次のような構造を持つ Maven プロジェクトが作成されます。

sample-project
├── README.md
├── pom.xml
└── src
    ├── main
    │   ├── java
    │   │   └── com
    │   │       └── test
    │   │           ├── App.java
    │   │           ├── DependencyFactory.java
    │   │           └── Handler.java
    │   └── resources
    │       └── simplelogger.properties
    └── test
        └── java
            └── com
                └── test
                    └── HandlerTest.java

App.java クラスは、アプリケーションのエントリーポイントです。DependencyFactory.java クラスには、構成された SDK クライアントが含まれています。

アプリケーショのビルド

アプリケーションをビルドするには、次のコマンドを実行します。

# 作成したプロジェクトディレクトリに移動します
# 名前は artifactId で指定した名前と同じである必要があります
cd sample-project

# アプリケーションをビルドする
mvn clean package

ネイティブな実行可能ファイルの作成

次のコマンドを実行して、ネイティブイメージを作成できます。

mvn clean package -P native-image

完了すると、ターゲットフォルダに実行可能ファイルが生成されます。名前は、指定された artifactId と同じである必要があります。

-H:ReflectionConfigurationResources=META-INF/native-image/software.amazon.awssdk/s3/reflect-config.json \
-H:EnableURLProtocols=https \
-H:+ReportUnsupportedElementsAtRuntime \
-H:ReflectionConfigurationResources=META-INF/native-image/software.amazon.awssdk/sdk-core/reflect-config.json \
-H:ResourceConfigurationResources=META-INF/native-image/software.amazon.awssdk/sdk-core/resource-config.json \
-H:ReflectionConfigurationResources=META-INF/native-image/software.amazon.awssdk/apache-client/reflect-config.json \
-H:ResourceConfigurationResources=META-INF/native-image/software.amazon.awssdk/apache-client/resource-config.json \
-H:DynamicProxyConfigurationResources=META-INF/native-image/software.amazon.awssdk/apache-client/proxy-config.json \
-H:FallbackThreshold=0 \
-H:ClassInitialization=org.slf4j:build_time \
-H:Class=com.test.App \
-H:Name=sample-project \
-H:CLibraryPath=/Library/Java/JavaVirtualMachines/graalvm-ce-java8-21.0.0/Contents/Home/jre/lib/svm/clibraries/darwin-amd64 \

]
[sample-project:33940]    classlist:   6,671.68 ms,  1.36 GB
[sample-project:33940]        (cap):   4,022.10 ms,  1.36 GB
[sample-project:33940]        setup:   6,922.21 ms,  1.36 GB
[sample-project:33940]     (clinit):   1,352.10 ms,  2.80 GB
[sample-project:33940]   (typeflow):  33,266.42 ms,  2.80 GB
[sample-project:33940]    (objects):  16,911.48 ms,  2.80 GB
[sample-project:33940]   (features):   1,717.77 ms,  2.80 GB
[sample-project:33940]     analysis:  54,700.08 ms,  2.80 GB
[sample-project:33940]     universe:   4,559.62 ms,  2.81 GB
[sample-project:33940]      (parse):  13,027.95 ms,  3.06 GB
[sample-project:33940]     (inline):   9,664.36 ms,  3.70 GB
[sample-project:33940]    (compile):  73,425.18 ms,  4.75 GB
[sample-project:33940]      compile: 100,632.59 ms,  4.75 GB
[sample-project:33940]        image:  10,399.21 ms,  4.82 GB
[sample-project:33940]        write:   1,834.74 ms,  4.82 GB
[sample-project:33940]      [total]: 186,280.64 ms,  4.82 GB
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  03:12 min
[INFO] Finished at: 2021-02-17T15:12:31-08:00
[INFO] ------------------------------------------------------------------------

ネイティブ実行可能ファイルの実行

ネイティブイメージを実行するには、次のコマンドを実行します。

target/sample-project

出力は次のようになります。

2021-02-17 15:13:18:071 -0800 [main] INFO com.test.App - Application starts
2021-02-17 15:13:18:086 -0800 [main] INFO com.test.App - Application ends

まとめ

このブログ記事では、AWS SDK for Java 2x を使用して、アプリケーションをネイティブイメージとしてコンパイルする利点について説明しました。また、新しい archetype を使用して、AWS SDK for Java 2.x を使用した、ネイティブイメージ互換のアプリケーションをすぐに開始できることを紹介しました。この archetype について 詳細に知りたい場合は、GitHub の archetype-app-quickstart のソースコードをチェックしてください。

よろしければ、この新しい archetype をお試し頂き、GitHub issues ページからご意見をお寄せください。

Zoe Wang

Zoe Wang

Zoe はソフトウェア開発エンジニアとして、AWS SDK for Javaの開発に携わっています。
彼女は開発者エクスペリエンスを向上させるためのツールの構築に情熱を注いでいます。ZoeのGitHubアカウントは @zoewangg です。


この記事の翻訳は、ソリューションアーキテクトの宮島 嶺が担当しました。