How the JVM chooses
If the machine has fewer than two CPUs or less than about 1.8 GB of memory, the JVM treats it as a "client" machine and uses the Serial collector. Otherwise it uses G1. Check what yours picked:
java -XX:+PrintFlagsFinal -version | grep -E "Use(Serial|Parallel|G1|Z)GC"
The options
| Collector | Flag | Good for | Cost |
|---|---|---|---|
| Serial | -XX:+UseSerialGC | One or two CPUs, heaps under about 1 GB, small APIs | Stops the application during GC, fine for small heaps |
| Parallel | -XX:+UseParallelGC | Batch jobs and maximum throughput | Longer pauses on big heaps |
| G1 | -XX:+UseG1GC | General purpose web apps, heaps of 2 GB and up | More memory and CPU overhead than Serial |
| ZGC | -XX:+UseZGC | Large heaps, strict latency | Needs more memory headroom, generational by default in recent Java |
Practical advice
- 2 GB server with one small app: Serial with a heap of 256 to 768 MB. It has the smallest footprint, and pauses of tens of milliseconds are not noticeable.
- 4 to 8 GB web application: leave G1 as it is. Set
-Xmsequal to-Xmxfor steady behaviour if you like. Do not tune G1 pause targets unless you measured a problem. - Large heaps or latency-sensitive APIs: try ZGC on Java 21 or later. Give it more room: the heap must be larger than the live data by a good margin.
Measure, do not guess
-Xlog:gc*:file=/var/log/myapp/gc.log:time,uptime:filecount=5,filesize=10m
Look at pause times and at how much memory is freed after each collection. Change one thing at a time, and run it under real load before you decide. A well-sized heap matters more than the choice of collector: see JVM heap settings and the heap calculator.
On managed plans we tune memory and garbage collection for your application.
Last updated October 29, 2026.