Amazon Elastic Container Service (Amazon ECS) に保存されている Java アプリケーションで「heap out of memory」というエラーが表示されました。このエラーをトラブルシューティングするために、.hprof ファイルを作成して Amazon Simple Storage Service (Amazon S3) バケットに保存したいと考えています。
簡単な説明
OutOfMemoryError 例外が発生する最も一般的な理由は、Java 仮想マシン (JVM) がヒープに十分なメモリーを割り当てられないことです。Java アプリケーションを ECS コンテナで実行すると、「heap out of memory」エラーが発生してアプリケーションが中断され、ECS タスクが停止します。アプリケーションが保存した.hprof ファイルは完全に使用できなくなります。例外エラーのトラブルシューティングや、メモリ割り当ての問題のデバッグを行うには、.hprof ファイルを作成して S3 バケットに保存する必要があります。
解決策
注: 次の解決策により、ほとんどのOutOfMemoryError 例外シナリオが解決します。Java メモリエラーの原因の詳細については、Oracle の Web サイトの「Understand the OutOfMemoryError exception」を参照してください。
S3 バケットの作成
Amazon S3 コンソールを使用して、.hprof ファイルを保存するための S3 バケットを作成します。
ECS タスク定義を作成する
Amazon ECS コンソールを使用して、Java アプリケーションの設計図となるタスク定義を作成します。
環境変数には、S3 バケットの名前を指定します。アプリケーションの初期化コマンドでも S3 バケット名を使用します。
注: HEAP_DUMP_BUCKET は、サンプルコマンドの環境変数です。
ECS タスクの IAM ロールを作成する
s3:PutObject アクセス許可がある、ECS タスクの AWS Identity and Access Management (IAM) ロールを作成して、ファイルをアップロードできるようにします。
初期化コマンドを実行する
JVM 作業ディレクトリに、デフォルトのヒープダンプが java_pidpid.hprof という名前のファイルで作成されます。別のファイル名またはディレクトリを指定するには、XX:HeapDumpPath= オプションを使用します。
ヒープダンプは、次の初期化コマンド例の /tmp/heap_dump.hprof ディレクトリに生成されます。
CMD ["java", \
"-XX:+HeapDumpOnOutOfMemoryError", \
"-XX:HeapDumpPath=/tmp/heap_dump.hprof", \
"-XX:OnOutOfMemoryError=yum install -y aws-cli > /dev/null && aws s3 mv /tmp/heap_dump.hprof s3://$HEAP_DUMP_BUCKET/'date+%F_%T'.hprof ; kill -9 %p", \
"MemoryApp" \]
初期化コマンドフローの例
**注:**AWS コマンドラインインターフェイス (AWS CLI) コマンドの実行中にエラーが発生した場合は、「AWS CLI エラーのトラブルシューティング」を参照してください。また、AWS CLI の最新バージョンを使用していることを確認してください。
OnOutOfMemoryError オプションは、OutofMemoryError 例外が発生した場合に実行するコマンドまたはスクリプトを指定します。OnOutOfMemoryError オプションの詳細については、Oracle ウェブサイトの「Java HotSpot VM command-line options」を参照してください。
OnOutOfMemoryError コマンドフローについては、以下の手順を実行します。
- AWS コマンドラインインターフェイス (AWS CLI) を**-y** 内にインストールします。手動による操作は不要です。コマンド出力が /dev/null の一時ファイルに保存されるため、AWS CLI のインストールに関する不要な情報がコンテナログに追加されることはありません。
- ECS タスクロールからのアクセス許可を使用して、.hprof ファイルを S3 バケットにアップロードします。.hprof ファイルの名前は、日付+%F_%T.hprofのパターンにに従って変更されます。
- Amazon CloudWatch のログデータを確認します。
2023-05-02T17:02:37.748+01:00 Hello, world! Hello Java! Good bye memory...
2023-05-02T17:02:37.748+01:00 Going to sleep for 2 ms...
2023-05-02T17:02:39.748+01:00 Wake now, lets heap the memory...
2023-05-02T17:02:39.748+01:00 java.lang.OutOfMemoryError: Requested array size exceeds VM limit
2023-05-02T17:02:39.748+01:00 Dumping heap to /tmp/heap_dump.hprof ...
2023-05-02T17:02:39.756+01:00 Heap dump file created [2893599 bytes in 0.008 secs]
2023-05-02T17:02:39.756+01:00 #
2023-05-02T17:02:39.757+01:00 # java.lang.OutOfMemoryError: Requested array size exceeds VM limit
2023-05-02T17:02:39.757+01:00 # -XX:OnOutOfMemoryError="yum install -y aws-cli > /dev/null && aws s3 mv /tmp/heap_dump.hprof s3://$HEAP_DUMP_BUCKET/`date +%F_%T`.hprof ; kill -9 %p"
2023-05-02T17:02:39.757+01:00 # Executing /bin/sh -c "yum install -y aws-cli > /dev/null && aws s3 mv /tmp/heap_dump.hprof s3://$HEAP_DUMP_BUCKET/`date +%F_%T`.hprof "...
2023-05-02T17:02:54.663+01:00 Completed 256.0 KiB/2.8 MiB (2.2 MiB/s) with 1 file(s) remaining
Completed 512.0 KiB/2.8 MiB (4.4 MiB/s) with 1 file(s) remaining
Completed 768.0 KiB/2.8 MiB (6.6 MiB/s) with 1 file(s) remaining
Completed 1.0 MiB/2.8 MiB (8.7 MiB/s) with 1 file(s) remaining
Completed 1.2 MiB/2.8 MiB (10.8 MiB/s) with 1 file(s) remaining
Completed 1.5 MiB/2.8 MiB (12.9 MiB/s) with 1 file(s) remaining
Completed 1.8 MiB/2.8 MiB (15.0 MiB/s) with 1 file(s) remaining
Completed 2.0 MiB/2.8 MiB (17.0 MiB/s) with 1 file(s) remaining
Completed 2.2 MiB/2.8 MiB (19.1 MiB/s) with 1 file(s) remaining
Completed 2.5 MiB/2.8 MiB (21.1 MiB/s) with 1 file(s) remaining
Completed 2.8 MiB/2.8 MiB (23.1 MiB/s) with 1 file(s) remaining
Completed 2.8 MiB/2.8 MiB (13.0 MiB/s) with 1 file(s) remaining move: ../tmp/heap_dump.hprof to s3://fargate-test-cluster-logs/2023-05-02_16:02:53.hprof
2023-05-02T17:02:54.705+01:00 Executing /bin/sh -c "kill -9 1"...
2023-05-02T17:02:54.707+01:00 Exception in thread "main" java.lang.OutOfMemoryError: Requested array size exceeds VM limit
2023-05-02T17:02:54.707+01:00 at MemoryApp.main(MemoryApp.java:13)
前述のログデータの例では、Amazon Corretto 17 イメージを実行するコンテナで AWS CLI の yum install を使用しています。コンテナイメージが異なるオペレーティングシステム (OS) に基づくものである場合、コマンドが変わります。以下は、別のオペレーティングシステムの場合のコマンド例です。
- Fedora Linux: dnf install -y awscli
- Debian: apt-get install -y awscli
- Alpine Linux: apk add aws-cli
**注:**どの OS においても、AWS CLI をインストールするコマンド例である yum install と同等のコマンドを使用する必要があります。