← Debugging Guides

阅读中文版本

Gradle Daemon OutOfMemoryError — Build JVM Heap

Fix Gradle daemon OutOfMemoryError by raising daemon heap, stopping stale daemons, and separating build JVM memory from test JVM memory.

intermediatedebuggingjavagradlememory

Symptoms

  • Gradle build fails with "Expiring Daemon because JVM heap space is exhausted"
  • The build is slower every run until it dies
  • java.lang.OutOfMemoryError: Java heap space during compile or test

Possible causes

  • The Gradle daemon heap is set below what the build needs
  • Multiple stale daemons hold memory and never restart
  • Test tasks run in the build JVM rather than a forked one

Diagnosis steps

List running Gradle daemons

gradle --status

Interpretation

Several idle daemons of mixed versions indicate stale processes worth stopping.

Reproduce with explicit heap

gradle -Dorg.gradle.jvmargs="-Xmx2g" build --no-daemon

Interpretation

If a larger heap or no-daemon succeeds, the daemon memory was the limit.

Root cause

Gradle runs the build inside a long-lived daemon JVM. When its heap cannot hold the build model, cached scripts, and compilation, the JVM throws OutOfMemoryError and the daemon expires, failing the build.

Fix

Raise org.gradle.jvmargs -Xmx, stop stale daemons with gradle --stop, fork tests with maxHeapSize, and enable the configuration cache to reduce retained state.

Risk note

Very large heaps increase GC pause and reduce build cache efficiency; size to actual need and measure.

Verify the fix

Rerun the build after the change and confirm it completes without OutOfMemoryError; check gradle --status shows a single healthy daemon.

Symptoms

This debugging guide addresses “Gradle Daemon OutOfMemoryError — Build JVM Heap”. Start from the symptoms, follow the ordered diagnostics, and confirm each hypothesis before moving on; the fix and verification steps then close the loop.

Observed symptoms include:

  • Gradle build fails with “Expiring Daemon because JVM heap space is exhausted”
  • The build is slower every run until it dies
  • java.lang.OutOfMemoryError: Java heap space during compile or test

Reproduce and Diagnose

Reproduce the failure in isolation before changing any code. Work through the checks below in order; each one narrows the search space.

Step 1: List running Gradle daemons

gradle --status

Several idle daemons of mixed versions indicate stale processes worth stopping.

Step 2: Reproduce with explicit heap

gradle -Dorg.gradle.jvmargs="-Xmx2g" build --no-daemon

If a larger heap or no-daemon succeeds, the daemon memory was the limit.

Likely contributors, in order of frequency:

  • The Gradle daemon heap is set below what the build needs
  • Multiple stale daemons hold memory and never restart
  • Test tasks run in the build JVM rather than a forked one

Root Cause

Gradle runs the build inside a long-lived daemon JVM. When its heap cannot hold the build model, cached scripts, and compilation, the JVM throws OutOfMemoryError and the daemon expires, failing the build.

The Fix

Raise org.gradle.jvmargs -Xmx, stop stale daemons with gradle –stop, fork tests with maxHeapSize, and enable the configuration cache to reduce retained state.

Watch out: Very large heaps increase GC pause and reduce build cache efficiency; size to actual need and measure.

# gradle.properties
org.gradle.jvmargs=-Xmx4g -XX:MaxMetaspaceSize=1g -XX:+UseParallelGC
org.gradle.caching=true
org.gradle.configuration-cache=true

# build.gradle.kts: give tests their own heap
tasks.withType<Test> {
    maxHeapSize = "2g"
}

Verify and Prevent

Rerun the build after the change and confirm it completes without OutOfMemoryError; check gradle –status shows a single healthy daemon.

Once verified, add a regression test that reproduces the original symptom so the failure cannot silently return.

This class of failure is usually environmental rather than pure logic, so capture the exact command, the environment variables, and the working directory in your bug report. Reproduce it in the smallest possible script, then widen the scope only once the minimal case is understood. A short written checklist for this failure mode saves hours the next time it appears.