Diagnosing OOMKilled in Spring Boot Container: Step-by-Step
Fast recall
Quick revision
Core answer
kubectl describe pod or docker inspect; (2) check current heap and non-heap usage with Actuator /metrics or jcmd 1 GC.heap_info; (3) compare RSS against container limit; (4) take a heap dump with jmap -dump and analyze with Eclipse MAT for leaks; (5) fix root cause: tune MaxRAMPercentage, find leak, or raise the limit.Practical incident-response skills for the most common containerized JVM production issue
Reflexively raising the memory limit without finding root cause — hides a memory leak that grows back to the new limit
Distinguish heap leaks from non-heap (Metaspace, direct buffers) leaks, mention NMT (Native Memory Tracking) for non-heap diagnosis, and explain why JVM error logs do NOT appear for OOMKilled (kill is external)
Interview-ready guide
Interview answer
Exit 137 means the kernel killed the container because it exceeded its cgroup memory limit — the JVM had no chance to react.
Step 1 — confirm OOMKilled, not some other 137 cause
kubectl describe podshowsReason: OOMKilledandExit Code: 137in the container's last state — confirm both before assuming OOM- For Docker,
docker inspectreturns true; on the host,--format '{{.State.OOMKilled}}' dmesg | grep killedshows the kernel kill log
Step 2 — read the memory history before the kill
- Without metrics from the previous incarnation, you cannot diagnose root cause; if Actuator + Prometheus or Datadog is not in place, install it first and wait for the next kill
- Plot
container_memory_working_set_bytes(RSS the kernel counts) alongsidejvm_memory_used(heap) andjvm_memory_used{area=nonheap}over the 30 minutes preceding the kill — the shape of the curves tells you the cause
Step 3 — differentiate heap leak vs non-heap leak vs under-sized container
- Heap rising monotonically → heap leak; take a heap dump with
jcmd 1 GC.heap_dump /tmp/heap.hprof, copy out, analyze with Eclipse MAT's Leak Suspects report — usually finds an unbounded cache, leaked listener, or escaped ThreadLocal - Heap stable but Metaspace or direct buffers growing → classloader or NIO leak; enable
-XX:NativeMemoryTracking=summaryandjcmd 1 VM.native_memory summaryto see which non-heap category is growing - Both heap and non-heap stable but RSS hits limit fast → the container is just under-sized; tune
MaxRAMPercentagefrom 75% down to 60% or raise the limit
Step 4 — fix the root cause, not the symptom
- For a heap leak, the fix is in the application code (add eviction, fix the cleanup); for a non-heap leak, the fix may be tuning a JVM flag (
MaxMetaspaceSize,MaxDirectMemorySize) or fixing the leak - Raising the container limit without finding the leak just delays the next OOMKill until the leak grows into the new limit — leaks have nowhere to go but up
Long-term hardening
- Always run with Actuator + Prometheus exporters so the next incident has metrics; add
-XX:+HeapDumpOnOutOfMemoryErrorwith a PersistentVolume mount so in-JVM OOMs leave a dump behind - Set memory requests = limits for the QoS Guaranteed class, ensuring the pod is evicted last under node pressure
Diagnosing OOMKilled in Spring Boot Container: Step-by-Step
Direct Answer
Exit code 137 = SIGKILL from kernel OOM killer because container exceeded memory limit. Diagnosis order: (1) confirm OOMKilled with kubectl describe pod or docker inspect; (2) check current heap and non-heap usage with Actuator /metrics or jcmd 1 GC.heap_info; (3) compare RSS against container limit; (4) take a heap dump with jmap -dump and analyze with Eclipse MAT for leaks; (5) fix root cause: tune MaxRAMPercentage, find leak, or raise the limit.
Common Mistakes & Pitfalls
Reflexively raising the memory limit without finding root cause — hides a memory leak that grows back to the new limit
Check your understanding
Answer these without looking back at the article.
- What is the difference between a heap OutOfMemoryError and a kernel OOMKill?
- How does Eclipse MAT's Leak Suspects report identify retained objects?
- What is Native Memory Tracking and what categories does it expose?
- Why does HeapDumpOnOutOfMemoryError NOT fire for an OOMKilled container?
Related interview prep categories
2Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.