Short answer
First read the message — it names the cause: Java heap space (heap too small or a leak), Metaspace (classloader leak), GC overhead limit exceeded (GC running constantly for little gain), unable to create new native thread, or Direct buffer memory.
Explanation
Always run with -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=... so you get a dump at the moment of failure, then analyze it in Eclipse MAT (dominator tree, leak suspects). Confirm whether it is a genuine leak (rising post-GC baseline) versus undersized heap (raise -Xmx) or a load spike. Check GC logs for the pattern before OOM.
Common mistakes
- Treating all OOMs the same.
- Not reading the message (Java heap space versus Metaspace versus GC overhead).