Surefire "forked VM terminated without saying goodbye" in CI - Fix Test OOM
This Surefire message means the forked test JVM vanished without reporting back - it was terminated externally (an OOM kill from the kernel, or a System.exit) rather than crashing cleanly. On constrained CI runners the cause is usually memory exhaustion.
What this error means
Tests stop with The forked VM terminated without properly saying goodbye. VM crash or System.exit called? and a Command was /bin/sh -c ... java .... The dmesg/log often shows the process was OOM-killed (exit 137).
[ERROR] Failed to execute goal ...maven-surefire-plugin:3.2.5:test on project app:
[ERROR] The forked VM terminated without properly saying goodbye. VM crash or System.exit called?
[ERROR] Command was /bin/sh -c cd /work && /opt/jdk/bin/java -jar surefire.jar ...Common causes
Test JVM OOM-killed on a constrained runner
The forked JVM (heap + Metaspace + Testcontainers/process overhead) exceeds the runner's memory and the kernel OOM-kills it, so it never says goodbye. This is the transient, capacity-driven case.
A test called System.exit or crashed natively
A test (or library) that calls System.exit, or a native/JNI crash, also makes the fork disappear without reporting - a deterministic cause unrelated to memory.
How to fix it
Give the forked JVM more headroom
Cap heap below the runner limit and reduce fork parallelism so concurrent JVMs fit in RAM.
<configuration>
<argLine>@{argLine} -Xmx1536m -XX:MaxMetaspaceSize=384m</argLine>
<forkCount>1</forkCount>
<reuseForks>true</reuseForks>
</configuration>Rule out System.exit / native crashes
- Search tests for stray
System.exit(...)calls and remove them. - Check the runner log/dmesg for an OOM kill (exit 137) versus a JVM hs_err crash file.
- If native, capture the
hs_err_pid*.logto identify the failing library.
How to prevent it
- Size the forked JVM and fork count to the runner's memory, forbid
System.exitin tests, and run memory-heavy suites on larger runners.