Short answer
The core trade-off is pause time vs throughput vs footprint.
Explanation
Serial is simplest with the least overhead but is single-threaded STW and pauses scale with heap size — good for small heaps/containers. G1 (default since Java 9) divides the heap into regions and balances a configurable pause target (e.g. 200ms) against throughput on large heaps. ZGC (and Shenandoah) are concurrent, do compaction with load/colored-pointer barriers, and target sub-millisecond pauses roughly independent of heap size (multi-terabyte heaps) at some throughput/CPU cost.
Common mistakes
- Saying ZGC is always best.
- Ignoring throughput versus latency trade-offs.