OutOfMemoryError: Java heap space, explained and fixed

java.lang.OutOfMemoryError: Java heap space means the garbage collector ran, reclaimed everything it could, and there was still no room for a new object. The heap is full of objects that are still reachable, either because the workload genuinely needs that much data in memory, or because a leak keeps references to objects that should have been released. Raising the heap limit is the correct remedy for the first and a postponement for the second, so the first job is telling them apart.

Tell a leak from a workload

  1. Watch heap usage across a garbage collection boundary (with jstat -gcutil, VisualVM, or the platform's metrics). A leak's baseline climbs after every collection, cycle over cycle, during steady work. A workload problem spikes with a particular job and returns to a healthy baseline.
  2. Note when it dies: minutes after a specific large operation starts (a report, an import, a batch) points at the workload; after hours or days of normal traffic, at no special moment, points at a leak.

The fixes, matched to the cause

  1. For a legitimate workload, raise the limit deliberately: -Xmx2g (or the appropriate size) on the launch command, sized against the machine's actual RAM and the other processes sharing it. In containers, set the flag explicitly; JVM ergonomics read container limits in modern versions, but an explicit value removes the guesswork.
  2. For a leak, capture the evidence before restarting: add -XX:+HeapDumpOnOutOfMemoryError so the next failure writes a heap dump, then open it in an analyzer (Eclipse MAT, VisualVM) and read the largest retained objects and what references them; a growing cache, collection, or listener list is the usual finding.
  3. Reduce the footprint of big jobs: stream records instead of loading whole result sets and files, page queries, and avoid holding both the raw and processed copies of large data at once.
  4. Bound every cache: an in-memory cache without a size limit or expiry is the most common self-inflicted leak in long-running services; use a bounded cache implementation.
An OutOfMemoryError can leave the process in a corrupt half-state, some threads died mid-operation and others did not. Restart the process after capturing the dump; do not let a service that has thrown this error keep serving traffic.

Common questions

What is the default heap size? It is chosen by JVM ergonomics from the machine's (or container's) memory, commonly a quarter of available RAM up to a cap on small systems. Print the effective value with java -XX:+PrintFlagsFinal -version and look for MaxHeapSize.

Is “GC overhead limit exceeded” the same problem? It is the sibling error: the collector spends nearly all its time reclaiming almost nothing, which means the same full-of-live-data heap. Diagnose it identically.

Will more RAM on the machine fix it without flags? Only if the JVM's ergonomics raise the heap in response, which is not guaranteed and is capped. Setting -Xmx deliberately is the reliable route for a workload that needs it.

Related errors

StackOverflowError · Could not create the Java Virtual Machine · Node: JavaScript heap out of memory