-XX:+HeapDumpOnOutOfMemoryError必须配合-XX:HeapDumpPath指定宿主机可持久化挂载路径(如/dump/),否则容器销毁后快照丢失;需volumeMounts挂载hostPath或PVC,设terminationGracePeriodSeconds≥60,并验证路径可写。
直接在 jvm 启动参数中加 -xx:+heapdumponoutofmemoryerror 是可行的,但默认会 dump 到容器内当前工作目录(通常不可写或路径不明确),而 pod 一旦 oom 被 k8s 杀掉,容器文件系统立即销毁——快照根本来不及保存。关键不是“加参数”,而是**确保 dump 文件能落盘到宿主机可持久化位置,并在 pod 终止前完成写入**。
必须挂载可写且宿主机可见的存储路径
不能依赖容器内部临时路径(如 /tmp 或镜像根目录)。需通过 volumeMounts 将宿主机目录(或 PV/PVC)挂载进容器,并指定为 dump 目标路径:
- 推荐使用
hostPath挂载节点本地目录(例如/var/log/myapp/heapdumps),确保该目录在所有调度节点上存在、可写、有足够空间 - 若用 PVC,需确认底层存储支持同步写(如 NFS 需配
sync选项,避免缓存延迟导致 dump 未落盘就被 kill) - 挂载时设置
readOnly: false,并在容器内验证权限:kubectl exec -it <pod> -- ls -ld /dump
JVM 参数要明确指定 dump 文件路径
仅开 -XX:+HeapDumpOnOutOfMemoryError 不够,必须配合 -XX:HeapDumpPath 指向已挂载的可写路径:
- 示例启动参数:
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/dump/oom-heap.hprof - 支持时间戳占位符(JDK 8u92+):
-XX:HeapDumpPath=/dump/heap-dump-%p-%t.hprof(%p是 PID,%t是 UNIX 时间戳),避免重复覆盖 - 务必确认该路径在容器内真实存在且可写,否则 JVM 会静默失败(不报错,也不生成文件)
增强可靠性:加超时与主动触发兜底
OOMKilled 是瞬时事件,依赖自动 dump 仍有风险。建议双保险:
- 在容器启动脚本中,用
trap 'jmap -dump:live,format=b,file=/dump/manual-$(date +%s).hprof $(pgrep java)' TERM INT EXIT,确保容器被终止前强制抓一次堆 - 配置 Liveness Probe 为 HTTP 健康检查而非 exec,避免因 jmap 卡住导致误杀;同时设
terminationGracePeriodSeconds: 60(默认30秒太短),给 dump 留出写入缓冲时间 - 配合
resources.limits.memory设置合理上限(如1Gi),让 OOM 发生在可控范围内,而非被 kubelet 突然 evict
快照抢救:Pod 销毁后从节点取回
dump 文件实际落在宿主机挂载路径,Pod 虽销毁,文件仍在:
- 查 Pod 调度节点:
kubectl get pod <pod-name> -o wide - 登录对应节点,进入挂载路径(如
/var/log/myapp/heapdumps/),确认文件存在且完整(ls -lh+file heap-dump-*.hprof) - 用
scp或rsync复制到分析机,用 MAT 或 VisualVM 分析(注意 JDK 版本兼容性)

















