我如何将 Java 堆转储文件导出到 S3 存储桶?

3 分钟阅读
0

我存储在 Amazon Elastic Container Service (Amazon ECS) 中的 Java 应用程序中出现“堆内存不足”错误。为了解决此错误,我想创建一个 .hprof 文件,并将其保存在 Amazon Simple Storage Service (Amazon S3) 存储桶中。

简述

您收到 OutOfMemoryError 异常的最常见原因是 Java 虚拟机 (JVM) 无法为堆分配足够的内存。当 Java 应用程序在 ECS 容器中运行时,“堆内存不足”错误会中断应用程序并停止 ECS 任务。应用程序保存的所有 .hprof 文件都不能再使用。要解决异常错误、调试内存分配问题,您必须创建一个 .hprof 文件并将其保存到 S3 存储桶。

解决方法

注意: 以下解决方法可以解决大多数 OutOfMemoryError 异常场景。有关 Java 内存错误原因的更多信息,请参阅 Oracle 网站上的了解 OutOfMemoryError 异常

创建 S3 存储桶

使用 Amazon S3 控制台创建 S3 存储桶来存储您的 .hprof 文件。

创建 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 命令行选项

完成 OnOutOfMemoryError 命令流的以下步骤:

  1. -y 中安装 AWS 命令行界面 (AWS CLI),无需交互。命令输出保存到 /dev/null 中的临时文件,以免关于 AWS CLI 安装的不必要的信息被添加到容器日志中。
  2. 使用 ECS 任务角色的权限将 .hprof 文件上传到 S3 存储桶。.hprof 文件会被重命名,采用 date+%F_%T.hprof 模式。
  3. 查看 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

注意: 对于任何操作系统,您都必须使用与安装 AWS CLI 的示例 yum install 命令等效的命令。