You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AWS ECS中Docker容器内Java应用因OOM重启,求内存排查方法

问题描述

我在AWS EC2(ECS)的Docker容器中运行一个部署在Tomcat服务器上的Java应用。近期该Java应用服务会不定期自动重启,查看ECS Agent日志后发现存在OutOfMemoryError。

ECS Agent日志信息:

Level: INFO
Message: DockerGoClient: Process within container 02118442aba47dbe536651b90ca1cd64c43ec419ea949dbe8ca3797f0df1dd71 (name: "my-java-app10-f8e5abadedfbd0c9d901") died due to OOM
Module: docker_client.go

Level: INFO
Message: Handling container change event
Task: 3825f1c6-0d3d-4771-bed7-15332dab4ad9
Container: service-layer
RuntimeID: 02118442aba47dbe536651b90ca1cd64c43ec419ea949dbe8ca3797f0df1dd71
Status: STOPPED

Level: WARN
Message: Error stopping the container; marking it as stopped anyway
Task: 3825f1c6-0d3d-4771-bed7-15332dab4ad9
Container: service-layer
RuntimeID: 02118442aba47dbe536651b90ca1cd64c43ec419ea949dbe8ca3797f0df1dd71
ErrorName: OutOfMemoryError
Error: Container killed due to memory usage

我无法确定具体是哪个Java线程/进程在占用内存。已尝试以下操作:

docker inspect <containerName>
docker ps --all (This shows Exited 137))

同时也查看了应用日志,但未发现异常调用。容器内存上限为1GB,此前运行正常,请问该如何排查持续占用内存的Java线程/进程?


排查方案

1. 配置JVM内存参数与OOM自动转储

修改Tomcat的JVM启动参数,添加内存溢出时的堆转储配置,保留OOM现场数据:

  • 在Tomcat的catalina.sh(Linux)或catalina.bat(Windows)中追加:
    JAVA_OPTS="$JAVA_OPTS -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/heapdump.hprof"
    
    确保容器内/tmp有足够空间,或指定到挂载的持久化目录,避免转储失败。
  • 结合容器1GB内存上限,调整JVM堆内存:建议设置-Xmx768m,预留部分内存给Tomcat系统进程,避免容器直接被OOM Killer终止。

2. 实时监控容器内Java进程内存

应用运行时,进入容器排查Java进程内存状态:

  • 进入容器:docker exec -it <container-id> /bin/bash
  • 查找Java进程ID:ps aux | grep java
  • 用jstat监控堆内存变化:jstat -gc <pid> 1000 10(每1秒输出一次,共10次),观察堆各区域(新生代、老年代)的内存占用趋势,判断是否存在内存泄漏。
  • 用jmap查看堆内存分布:jmap -histo <pid>,列出各类的实例数量与内存占用,定位内存消耗大户。

3. 分析堆转储文件

OOM发生后,导出堆转储文件并分析:

  • 复制文件到本地:docker cp <container-id>:/tmp/heapdump.hprof ./local-directory/
  • 使用Java分析工具(如Eclipse MAT、JVisualVM)打开文件:
    • MAT自动生成泄漏报告,找出占用内存最大的对象及其引用链,定位到具体代码逻辑。
    • JVisualVM对比不同时间点的堆快照,分析内存增长根源,同时可查看线程栈信息,排查线程内存占用。

4. 监控容器与ECS层面内存指标

  • 在AWS ECS控制台查看服务的CloudWatch内存监控指标,确认内存占用是否持续上升,是否在特定时段触发OOM。
  • 用docker stats <container-id>实时监控容器整体内存、CPU使用率,对比JVM内部内存数据,排查是否是堆外内存(如直接内存、NIO ByteBuffer)占用过高。

5. 排查代码与依赖变更

  • 检查近期代码改动,是否新增大量缓存、大对象创建、未关闭的资源(数据库连接、文件流)等逻辑。
  • 排查第三方依赖版本,确认是否存在已知的内存泄漏Bug。

内容的提问来源于stack exchange,提问作者Raghav91

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 21:35:31