Java "OutOfMemoryError: Java heap space" in CI - Fix Heap Sizing
The JVM tried to allocate on the heap but could not free enough space, and -Xmx was already reached. Either the heap ceiling is too low for the work, or something is holding more live objects than expected.
What this error means
A test run, compile, or application step fails with java.lang.OutOfMemoryError: Java heap space and a stack trace at the allocation site. It often appears under load - large fixtures, big datasets, or many parallel workers.
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.base/java.util.Arrays.copyOf(Arrays.java:3537)
at com.example.ReportBuilder.accumulate(ReportBuilder.java:88)Common causes
Heap ceiling too low for the workload
The default or configured -Xmx is smaller than the live data set needs. Loading large fixtures or building big in-memory structures hits the cap.
Excessive retained objects or a leak
Code that holds references longer than necessary (caches, static collections) keeps the heap full so GC cannot reclaim, and the next allocation fails.
How to fix it
Raise the heap for the failing process
Give the JVM more heap, sized below the runner’s total RAM to leave room for the OS and other JVMs.
# generic
java -Xmx4g -jar app.jar
# Maven Surefire forked JVM
mvn -B test -DargLine="-Xmx2g"
# Gradle forked test JVM (build.gradle.kts)
# test { maxHeapSize = "2g" }Reduce the memory footprint
- Stream or page large data instead of loading it all into memory.
- Lower test/compile parallelism so fewer JVMs share the runner RAM.
- Capture a heap dump (
-XX:+HeapDumpOnOutOfMemoryError) and find the dominant retained objects.
How to prevent it
- Set
-Xmxexplicitly relative to the runner RAM rather than relying on defaults. - Bound parallelism so concurrent JVMs do not oversubscribe memory.
- Profile heap usage so growth is caught before it OOMs in CI.