Tengo un error "heap out of memory" en mi aplicación Java que está almacenada en Amazon Elastic Container Service (Amazon ECS). Para solucionar el error, quiero crear un archivo .hprof y guardarlo en un bucket de Amazon Simple Storage Service (Amazon S3).
Descripción breve
La razón más común por la que se obtiene una excepción OutOfMemoryError es porque una máquina virtual Java (JVM) no puede asignar suficiente memoria a un montón. Cuando una aplicación Java se ejecuta en un contenedor de ECS, un error "heap out of memory" interrumpe la aplicación y detiene las tareas de ECS. Los archivos .hprof que guarda la aplicación ya no están disponibles. Para solucionar el error de excepción y depurar los problemas de asignación de memoria, debes crear un archivo .hprof y guardarlo en un bucket de S3.
Resolución
Nota: La siguiente resolución resuelve la mayoría de los escenarios de excepción de OutOfMemoryError. Para obtener más información sobre la causa de los errores de memoria de Java, consulta Understand the OutOfMemoryError exception (Información sobre la excepción OutOfMemoryError) en el sitio web de Oracle.
Creación de un bucket de S3
Utiliza la consola de Amazon S3 para crear un bucket de S3 para almacenar el archivo .hprof.
Creación de una definición de tarea de ECS
Utiliza la consola de Amazon ECS para crear una definición de tarea como esquema de la aplicación Java.
Para la variable de entorno, proporciona el nombre del bucket de S3. Los comandos de inicialización de la aplicación también utilizan el nombre del bucket de S3.
Nota: HEAP_DUMP_BUCKET es la variable de entorno de los comandos de ejemplo.
Creación de un rol de IAM para una tarea de ECS
Crea un rol de AWS Identity and Access Management (IAM) para la tarea de ECS que incluya permisos s3:PutObject para que puedas cargar archivos.
Ejecución de los comandos de inicialización
En el directorio de trabajo de JVM, se crea un volcado de montón predeterminado en un archivo denominado java_pidpid.hprof. Para especificar otro nombre de archivo o directorio, utiliza la opción XX:HeapDumpPath=.
En los siguientes ejemplos de comandos de inicialización, el volcado de la pila se genera en el directorio /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" \]
Ejemplo de flujo de comandos de inicialización
Nota: Si se muestran errores al ejecutar comandos de la Interfaz de la línea de comandos de AWS (AWS CLI), consulta Troubleshoot AWS CLI errors. Además, asegúrate de utilizar la versión más reciente de la AWS CLI.
La opción OnOutOfMemoryError especifica un comando o script que se ejecutará cuando recibas la excepción OutOfMemoryError. Para obtener más información sobre la opción OnOutOfMemoryError, consulta Java HotSpot VM command-line options (Opciones de la línea de comandos de Java HotSpot VM) en el sitio web de Oracle.
Completa los siguientes pasos del flujo de comandos OnOutOfMemoryError:
- Instala la Interfaz de la línea de comandos de AWS (AWS CLI) en**-y** sin ninguna interacción. El resultado del comando se guarda en un archivo temporal en /dev/null para que no se añada información innecesaria sobre la instalación de la AWS CLI a los registros del contenedor.
- Cargue el archivo .hprof al bucket de S3 con los permisos del rol de tarea de ECS. Se cambia el nombre del archivo .hprof para que siga el patrón fecha+%F_%T.hprof.
- Revisa los datos de registro de 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)
El ejemplo de datos de registro anterior utiliza yum install para la AWS CLI en un contenedor que ejecuta la imagen de Amazon Corretto 17. Si la imagen del contenedor se basa en un sistema operativo (SO) diferente, el comando cambia. A continuación se muestran ejemplos de comandos para diferentes sistemas operativos:
- Fedora Linux: dnf install -y awscli
- Debian: apt-get install -y awscli
- Alpine Linux: apk add aws-cli
Nota: Con cualquier sistema operativo, debes usar un comando equivalente al comando yum install de ejemplo que instala la AWS CLI.