How do you control the heap size of the JVM that runs your tests in Gradle, and where do you configure it?
answer
- tests fork a separate JVM
- minHeapSize=-Xms, maxHeapSize=-Xmx
- org.gradle.jvmargs sizes the DAEMON not tests
- each parallel fork gets its own heap
- string values like 512m / 2g
basics
~10 sTests run in a separate forked JVM. On the test task set minHeapSize and maxHeapSize (e.g. "256m" / "1g"). These map to the forked JVM's -Xms and -Xmx, not the Gradle daemon's heap.
solid answer
~40 sGradle's `Test` task forks one or more separate JVMs to actually run tests, isolated from the Gradle daemon. You size that forked JVM with `minHeapSize` and `maxHeapSize` on the `test` task, which become `-Xms` and `-Xmx` for the forked process. A common mistake is putting `-Xmx` in `org.gradle.jvmargs` (gradle.properties) expecting it to affect tests — that only sizes the daemon. For one-off control you can also pass `jvmArgs("-Xmx2g")`, but `maxHeapSize` is the idiomatic, readable property. Values are strings like "512m" or "2g". When tests run out of memory you raise `maxHeapSize`; raising the daemon heap has no effect on the forked test JVM.
code
kotlin · 6 linestasks.test {
minHeapSize = "256m"
maxHeapSize = "2g"
// equivalent low-level form:
// jvmArgs("-Xms256m", "-Xmx2g")
}go deeper
Know tests fork a separate JVM and that minHeapSize/maxHeapSize on the test task set -Xms/-Xmx.
Distinguish daemon heap (gradle.properties) from forked test heap; size per-worker memory with parallel forks in mind.
Reason about CI RAM budgeting: total ≈ forks × maxHeapSize; pick values that avoid both OOM and host thrashing.
Set org-wide defaults via a convention plugin so teams don't rediscover the daemon-vs-test-heap trap; standardize CI memory budgets.
## Why tests run in a separate JVM Gradle does not run your tests inside the long-lived Gradle daemon. The `Test` task **forks** one or more fresh JVMs (the *test workers*) and executes test classes there. This isolates test code — its static state, classloaders, custom JVM flags, and crashes — from the daemon that orchestrates the build. Because it is a distinct process, it has its **own** heap, its own system properties, and its own JVM arguments, all configured on the `test` task rather than inherited from the daemon. ## Heap properties The `Test` task (which extends `ProcessForkOptions`/`JavaForkOptions`) exposes: - `minHeapSize` → the forked JVM's `-Xms` (initial heap). - `maxHeapSize` → the forked JVM's `-Xmx` (maximum heap). Both are `String` properties taking values like `"256m"`, `"1g"`. Setting `maxHeapSize = "2g"` is exactly equivalent to adding `jvmArgs("-Xmx2g")`, but it is the readable, intention-revealing form. ## The classic confusion: daemon heap vs test heap `org.gradle.jvmargs=-Xmx4g` in `gradle.properties` sizes the **Gradle daemon**, the process that configures and runs the build graph. It does **not** size the forked test JVM. If your tests throw `OutOfMemoryError`, raising the daemon heap changes nothing — you must raise `maxHeapSize` on the `test` task. Conversely, a heavy test suite does not need a giant daemon heap. ## Where it applies With `maxParallelForks > 1` Gradle launches several test workers; **each** worker gets the heap you configured, so total memory ≈ `maxParallelForks × maxHeapSize`. Keep that in mind on CI agents with limited RAM. ```kotlin tasks.test { minHeapSize = "256m" maxHeapSize = "2g" } ```
- Tests OOM but you set -Xmx4g in gradle.properties. Why didn't it help?`org.gradle.jvmargs` in gradle.properties only sizes the Gradle daemon. The forked test JVM ignores it; you must set `maxHeapSize` (or jvmArgs -Xmx) on the `test` task.
- With maxParallelForks=4 and maxHeapSize=2g, what's the worst-case test memory footprint?Up to ~8g — each of the 4 workers gets its own 2g max heap simultaneously.
The daemon is the kitchen manager; each test worker is a separate cook with their own counter space. Giving the manager a bigger desk doesn't give the cooks more room — you size the workers directly.
saying these in an interview costs you the question
- Claiming tests run inside the Gradle daemon / share its heap.
- Believing org.gradle.jvmargs affects the test JVM's heap.
- Forgetting that parallel forks multiply total memory use.