Skip to content
Latchkey

Java "GC overhead limit exceeded" in CI - Fix Thrashing GC

The JVM gave up because it was spending more than 98% of its time in garbage collection and recovering less than 2% of the heap. It is a near-OOM: technically there is a sliver of heap left, but GC is thrashing.

What this error means

A long-running test or build slows to a crawl and then fails with java.lang.OutOfMemoryError: GC overhead limit exceeded. CPU is pegged on GC threads just before the failure.

JVM output
Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded
    at java.base/java.util.HashMap.resize(HashMap.java:704)

Common causes

Heap too small for the live set

When the live data nearly fills the heap, GC runs constantly but frees almost nothing. The overhead guard trips before a hard heap-space OOM.

Memory leak slowly filling the heap

A growing retained set (caches, accumulating collections) pushes the heap toward full, and GC overhead climbs until the limit is exceeded.

How to fix it

Increase the heap

A larger -Xmx gives GC room to reclaim, ending the thrashing - assuming there is no leak.

Terminal
java -Xmx4g -jar app.jar
mvn -B test -DargLine="-Xmx2g"

Find and fix the retention

If raising heap only delays the failure, capture a heap dump and locate what is being retained.

Terminal
java -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./oom.hprof -jar app.jar
# analyze oom.hprof with Eclipse MAT or VisualVM

How to prevent it

  • Size -Xmx so the live set leaves comfortable headroom for GC.
  • Profile for leaks when GC overhead climbs over time.
  • Avoid unbounded in-memory accumulation in long-running steps.

Related guides

Tired of flaky CI? Latchkey auto-heals failed jobs and retries them for you. Start free →