Super Java Host
  1. Home
  2. Guides
  3. Fix OutOfMemoryError

How to fix a Java OutOfMemoryError

The message after OutOfMemoryError tells you which memory ran out. Each kind has a different cause and a different fix.

1. Read the message

Search the log (journalctl -u yourservice, catalina.out or the application log) for OutOfMemoryError. The text after the colon decides everything:

MessageMeaningFix
Java heap spaceObjects do not fit in the heapRaise -Xmx or find the leak
GC overhead limit exceededThe JVM spends almost all its time in GC and frees almost nothingSame as heap space
MetaspaceToo many loaded classes, often from redeploysRaise MaxMetaspaceSize, restart instead of redeploying
unable to create native threadProcess or OS thread limit, or no memory for stacksFewer threads, lower -Xss, higher limits
Direct buffer memoryOff-heap buffers (Netty, NIO)Raise -XX:MaxDirectMemorySize

2. Is it the heap or the server?

If the log has no OutOfMemoryError but the service just disappeared, the Linux kernel killed it because the whole server ran out of RAM. Check:

sudo dmesg -T | grep -i -E "out of memory|killed process"
sudo journalctl -k | grep -i "killed process"
free -m

That is not a heap problem. The heap plus metaspace, thread stacks, the database and the OS exceed physical memory. Lower -Xmx (a bigger heap is often the wrong answer here), stop other memory users, or move to a bigger server. See how much RAM a Java app needs.

3. Heap space: leak or too small?

Turn on logging of garbage collections and a dump on failure. Add to the JVM options:

-Xlog:gc*:file=/var/log/myapp/gc.log:time,uptime:filecount=5,filesize=10m
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/var/tmp/myapp.hprof
-XX:+ExitOnOutOfMemoryError

Create the log folder and give the service user write access. Then read the log. If the heap after each full GC stays flat and the application is simply busy, the heap is too small: raise it. If the heap after full GC climbs over hours or days, that is a leak: no heap size will fix it, only delay it.

ExitOnOutOfMemoryError makes the JVM exit so systemd can restart it cleanly. A JVM that has thrown OOM is unreliable and best replaced.

4. Find the leak

Open the .hprof file in Eclipse Memory Analyzer (MAT) on your computer, not on the server. Run the Leak Suspects report. It shows the largest object trees and what holds them. Typical culprits: an unbounded cache or static map, sessions that never expire, a result set loaded entirely into memory, a thread local that is never cleared.

A quick look without a dump:

sudo -u appuser jcmd <pid> GC.class_histogram | head -20

Run it twice, a few minutes apart, and compare the leading classes.

5. Metaspace

Normal applications settle at 100 to 300 MB. Growth that never stops usually means a classloader leak: repeated hot redeploys in Tomcat or WildFly are the classic cause. The fix is to restart the service on deploy. Set a ceiling so it fails visibly instead of eating RAM: -XX:MaxMetaspaceSize=256m.

6. Cannot create native thread

ulimit -u                       # user process limit
cat /proc/<pid>/limits | grep -i processes
ps -o nlwp= -p <pid>            # threads of your JVM

If the thread count is in the thousands, look for an unbounded executor or a thread per request. Set TasksMax=infinity and a larger LimitNPROC in the systemd unit only if you really need that many threads.

What not to do

Do not set -Xmx to nearly all the RAM hoping it goes away. The heap is only part of the process, and you will trade a Java error for the kernel killing the process. Size the server instead: the JVM heap calculator gives a safe starting point.

Last updated October 29, 2026.

Your own Java server, billed monthly

Plans from €15.30 a month. Set up for you, or run for you.