GraalVM は、静的コンパイルによって Java アプリケーションの コールドスタートと実行時のメモリ消費量が多いという問題を解消するために使用されます。GraalVM アプリケーションの場合、Application Real-Time Monitoring Service (ARMS) は、Java 用 ARMS エージェントが実行時に使用するバイトコード変更ロジックを静的コンパイルに移行する静的インストゥルメンテーションソリューションを提供します。これにより、静的拡張とすぐに使える可観測性機能を実現します。
最先端の GraalVM アプリケーションは、最初にテスト環境にデプロイすることをお勧めします。技術サポートを受けるには、DingTalk グループ (ID: 80805000690) に参加してください。
制限事項
アプリケーションは、静的コンパイルに適応するように構成する必要があります。Spring Boot アプリケーションを使用している場合は、Spring Boot のドキュメントを参考にアプリケーションを構成できます。
静的コンパイルを実行する際は、ARMS が提供する GraalVM JDK を使用してください。
GraalVM の静的コンパイルには、環境に関する特定の要件があります。詳細については、GraalVM のドキュメントを参照してください。
ARMS は、GraalVM アプリケーションのトレースとメトリック監視を提供します。Arthas、継続的な診断、およびメモリ スナップショットはサポートされていません。GraalVM アプリケーションのメモリ管理は主流の JVM アプリケーションとは異なるため、JVM 監視固有のメタデータの詳細、非ヒープメモリ、およびダイレクトバッファにはデータがありません。
手順
ステップ 1: 依存関係をインストールする
必要な依存関係を環境にインストールします。
アプリケーションが存在するリージョンに基づいて ARMS エージェントをダウンロードします。
ARMS エージェントは、以下のリージョンで利用できます。技術サポートを受けるには、DingTalk グループ (ID: 80805000690) に参加してください。
リージョン
パブリック URL
VPC アドレス
中国 (杭州)
wget "http://arms-apm-cn-hangzhou.oss-cn-hangzhou.aliyuncs.com/ArmsAgentNative.zip" -O ArmsAgentNative.zip
wget "http://arms-apm-cn-hangzhou.oss-cn-hangzhou-internal.aliyuncs.com/ArmsAgentNative.zip" -O ArmsAgentNative.zip
中国 (上海)
wget "http://arms-apm-cn-shanghai.oss-cn-shanghai.aliyuncs.com/ArmsAgentNative.zip" -O ArmsAgentNative.zip
wget "http://arms-apm-cn-shanghai.oss-cn-shanghai-internal.aliyuncs.com/ArmsAgentNative.zip" -O ArmsAgentNative.zip
中国 (北京)
wget "http://arms-apm-cn-beijing.oss-cn-beijing.aliyuncs.com/ArmsAgentNative.zip" -O ArmsAgentNative.zip
wget "http://arms-apm-cn-beijing.oss-cn-beijing-internal.aliyuncs.com/ArmsAgentNative.zip" -O ArmsAgentNative.zip
中国 (張家口)
wget "http://arms-apm-cn-zhangjiakou.oss-cn-zhangjiakou.aliyuncs.com/ArmsAgentNative.zip" -O ArmsAgentNative.zip
wget "http://arms-apm-cn-zhangjiakou.oss-cn-zhangjiakou-internal.aliyuncs.com/ArmsAgentNative.zip" -O ArmsAgentNative.zip
中国 (深圳)
wget "http://arms-apm-cn-shenzhen.oss-cn-shenzhen.aliyuncs.com/ArmsAgentNative.zip" -O ArmsAgentNative.zip
wget "http://arms-apm-cn-shenzhen.oss-cn-shenzhen-internal.aliyuncs.com/ArmsAgentNative.zip" -O ArmsAgentNative.zip
中国南部 1 金融
なし
wget "http://arms-apm-cn-shenzhen-finance-1.oss-cn-shenzhen-finance-1-internal.aliyuncs.com/ArmsAgentNative.zip" -O ArmsAgentNative.zip
ARMS エージェントのインストールパッケージを解凍し、ArmsAgentNative ディレクトリに移動して、次のコマンドを実行して環境にインストールします。
sh install.sh
可観測性を提供する GraalVM JDK (graalvm-java17-23.0.4-ali-1.2b.tar.gz) をダウンロードします。
ファイルを解凍し、ディレクトリで次のコマンドを実行します。
graalvm-java17-23.0.4-ali-1.2b/bin/native-image --version
次の結果が返された場合、インストールは成功です。
Maven (apache-maven-3.8.4-bin.tar.gz) をダウンロードします。Maven をインストール済みの場合は、次のステップに進みます。
ファイルを解凍し、JAVA_HOME 変数を GraalVM のパスに、MAVEN_HOME 変数を Maven のパスに設定します。
サンプルコマンドでは、
/xxx/
を指定しています。export MAVEN_HOME=/xxx/apache-maven-3.8.4 export PATH=$PATH:$MAVEN_HOME/bin export JAVA_HOME=/xxx/graalvm-java17-23.0.4-ali-1.2b export PATH=$PATH:$JAVA_HOME/bin
ステップ 2: 依存関係を追加する
次の依存関係をアプリケーションに追加します。
コード内の /xxx/dynamic-configs
をアプリケーションの動的構成ファイルのパスに置き換えます。
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>arms-javaagent-native</artifactId>
<version>4.1.11</version>
<type>pom</type>
</dependency>
</dependencies>
<profiles>
<profile>
<id>native</id>
<build>
<plugins>
<plugin>
<groupId>org.graalvm.buildtools</groupId>
<artifactId>native-maven-plugin</artifactId>
<extensions>true</extensions>
<executions>
<execution>
<id>build-native</id>
<goals>
<goal>compile-no-fork</goal>
</goals>
<phase>package</phase>
</execution>
</executions>
<configuration>
<fallback>false</fallback>
<buildArgs>
<arg>-H:ConfigurationFileDirectories=native-configs,/xxx/dynamic-configs</arg>
</buildArgs>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
ステップ 3: access-filter-file.json ファイルを追加する
アプリケーションのディレクトリに access-filter-file.json ファイルを追加します。このファイルには、次の内容が含まれています。
{ "rules": [
{"excludeClasses": "sun.launcher.LauncherHelper"}
]
}
access-filter-file.json ファイルは、GraalVM で動的プロパティを収集するエージェントが sun.launcher.LauncherHelper
でリフレクションを収集するのを防ぎます。sun.launcher.LauncherHelper
は JVM の起動中に使用されるクラスであり、静的にコンパイルされたネイティブイメージにはそのリフレクションは必要ありません。リフレクションが収集されると、コンパイルエラーが発生します。
ステップ 4: アプリケーションを事前実行する
ARMS エージェントによって挿入された動的拡張コードが最終的なネイティブイメージファイルに静的にコンパイルされるようにするには、エージェントをマウントしてアプリケーションを事前に実行する必要があります。アプリケーションを事前実行する際は、アプリケーションのすべてのコアコードブランチが実行されるようにする必要があります。事前実行を支援するためのスクリプトが提供されています。アプリケーションのすべての RESTful インターフェースは、指示に従ってスクリプトで宣言する必要があるため、適切に呼び出してビジネス実行をトリガーできます。
必要に応じてスクリプトを変更します。
######## パラメータを変更する # ARMS 統合固有のパラメータ。LicenseKey の値は、DescribeTraceLicenseKey オペレーションを呼び出すことで取得できます。AppName の値をアプリケーション名に設定します。分散アーキテクチャでは、1 つのアプリケーションに複数のピアアプリケーションインスタンスを含めることができます。 export ARMS_LICENSEKEY= export ARMS_APPNAME= # アプリケーションインターフェースのリスト。サンプル値: (interface1 interface2 interface3 interface4)。 export PS= # アプリケーションポート。サンプル値: 8080。 export PORT= # 静的コンパイル後にアプリケーションの target ディレクトリにネイティブイメージファイルを保存するパス。サンプル値: target/graalvm-demo。 export NATIVE_IMAGE_FILE= # ARMS エージェントを実行するためのコマンド。サンプルコマンド: -javaagent:./arms-native/aliyun-java-agent-native.jar -jar target/graalvm-demo-1.0.0.jar。 export JAVA_CMD= ########
ARMS エージェントをマウントして事前実行を開始し、静的コンパイルの構成項目を収集します。
sh ArmsAgentNative/run.sh --collect --jvm --Carms
ステップ 5: アプリケーションを静的にコンパイルする
次の手順を実行して、アプリケーションを静的にコンパイルします。
静的コンパイルを開始します。
mvn -Pnative package
コンパイルされたプロジェクトを実行します。
sh ArmsAgentNative/run.sh --native --Carms
関連操作
Docker イメージをビルドする
静的にコンパイルされた GraalVM アプリケーションの Docker イメージをビルドする場合は、アプリケーションには JDK などの必要なすべての実行時情報が既に含まれているため、最終的なネイティブイメージファイルを実行可能ファイルとしてイメージに配置し、通常の Docker イメージビルドプロセスに従うことができます。
Dockerfile のサンプル:
-Darms.licenseKey
パラメータと -Darms.appName
パラメータを必要に応じて置き換えます。
FROM centos:latest
WORKDIR /app
COPY ./target/graalvm-demo /app
CMD ["/app/graalvm-demo","-Darms.licenseKey=xxx","-Darms.appName=xxx"]
ネイティブイメージを圧縮する
ネイティブイメージと Java プログラムのサイズを比較する場合、JDK は通常、Java プログラムの一部と見なされます。これは、Java プログラムには JDK のサポートが必要ですが、ネイティブイメージは自己完結型であり、既にすべての依存関係が含まれているためです。
ただし、ネイティブイメージはアセンブリコードで構成されているため、Java アプリケーションのバイトコードと比較して情報密度が低く、同じセマンティクスを表すためにより多くのコードが必要になります。その結果、アプリケーションのスケーリングに伴い、ネイティブイメージのサイズが最終的に Java プログラムと JDK の合計サイズを超える可能性があります。これにより、デプロイと転送の負荷が増加します。この場合、UPX などの圧縮ツールを使用して、ネイティブイメージのサイズを縮小できます。UPX は、バイナリ実行可能ファイルをより小さなバイナリ実行可能ファイルに圧縮でき、圧縮されたファイルは、実行時のパフォーマンスへの影響を最小限に抑えながら、解凍せずに直接実行できます。
次の図は、ネイティブイメージの圧縮を示しています。
静的にコンパイルされた graalvm-demo
ファイルを graalvm-demo-compressed
ファイルに圧縮します。後者のサイズは前者のサイズの 28.4% です。
次の図は、graalvm-demo、graalvm-demo-compressed、および Fat Jar のサイズを比較しています。
Spring Boot と RocketMQ のすべての依存関係を含む Fat JAR のサイズは 216 MB ですが、圧縮されたネイティブイメージのサイズはわずか 47 MB です。
UPX を使用するには、次の手順を実行します。
UPX のインストールパッケージをダウンロードして解凍します。
解凍後、UPX が
$UPX_HOME
ディレクトリにあるとします。次のコマンドを実行してファイルを圧縮します。$UPX_HOME/upx -9 -o path/to/output-file path/to/original-file
-9
: 圧縮レベル。1 から 9 の範囲です。値が大きいほど圧縮率は高くなりますが、圧縮にかかる時間は長くなります。-o path/to/output-file
: 圧縮された出力ファイルのパス。path/to/output-file を実際のファイルパスに置き換えます。path/to/original-file
: 元のファイルのパス。path/to/original-file を実際のファイルパスに置き換えます。