Docker中JVM OOM需配置-XX:+HeapDumpOnOutOfMemoryError与绝对路径的-XX:HeapDumpPath,确保目录存在、可写并挂载宿主机;OOM后用docker cp导出.hprof文件,再用MAT通过Leak Suspects和Dominator Tree定位泄漏点。

在 Docker 容器中应对 JVM 内存溢出(OOM),关键不是“等它挂了再救”,而是提前配置自动导出 + 确保文件可落盘 + 容器内外路径打通,最后用工具精准定位泄漏点。下面分四块说清楚。
容器启动时必须配全 dump 触发参数
仅加 -XX:+HeapDumpOnOutOfMemoryError 是无效的——JVM 默认尝试写到工作目录(通常是 / 或 /app),而容器内该路径往往不可写或被只读挂载。必须同时指定绝对路径,并确保该路径已存在、有权限:
- 推荐写法:
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/data/dump/oom_%p_%t.hprof -
%p表示进程 PID,%t是秒级时间戳,避免多实例覆盖 - 对应目录需在 Dockerfile 中提前创建:
RUN mkdir -p /data/dump && chown -R appuser:appuser /data/dump - 若用
docker run启动,记得挂载宿主机目录:-v /host/logs:/data/dump,并保证宿主机该路径有足够空间(dump 文件常达 2–10 GB)
Docker 环境下 dump 文件的获取与转移
OOM 发生后,dump 文件生成在容器内指定路径,但不能直接在容器里分析(资源受限、无 GUI)。需导出到宿主机:
- 确认容器 ID 和 dump 文件名:
docker exec -it <container_id> ls -l /data/dump/ - 拷贝到本地:
docker cp <container_id>:/data/dump/oom_*.hprof ./ - 若容器已退出,只要 volume 挂载有效且未清理,文件仍保留在宿主机映射路径中
- 注意:不要用
docker logs查 OOM 日志——JVM 的 OOM 异常默认输出到 stderr,但 dump 不依赖日志,靠的是 JVM 参数生效
分析工具选型与核心操作步骤
拿到 .hprof 文件后,不建议用 jhat(内存吃紧、界面简陋),优先用 MAT(Eclipse Memory Analyzer)或 IDEA 自带分析器:
立即学习“Java免费学习笔记(深入)”;
- MAT 打开后,先点 Leak Suspects Report —— 它会自动扫描并标出最可能的泄漏根因(比如某个静态 Map 持有上万对象)
- 接着看 Dominator Tree,按“Retained Heap”倒序排列,快速锁定吃内存的大户类
- 右键可疑对象 → Path to GC Roots(排除弱引用),查看谁在强引用它,最终定位到业务代码行
- IDEA 用户可直接拖入 .hprof 文件,内置分析器支持类实例数、内存占比、引用链可视化,无需额外安装
补充手段:非 OOM 场景下的手动抓取
有时服务卡顿、GC 频繁但没抛 OOM,这时要主动干预:
- 进容器执行:
jps -l找 Java 进程 PID,再运行:jmap -dump:live,format=b,file=/data/dump/manual.hprof <pid> - 若进程响应极慢,加
-F强制:jmap -F -dump:live,format=b,file=/data/dump/force.hprof <pid> - 注意:
jmap会触发全局 stop-the-world,慎用于生产高峰;建议搭配jstat -gcutil <pid> 1000先观察 GC 健康度 - 导出后同样走 MAT 分析流程,重点关注 “Objects per Class” 和 “Biggest Objects” 视图


















