Direct answer
Prove that pauses overlap garbage collection before changing JVM flags. High heap allocation is not itself a GC problem; correlate GC pause duration and time with the lag spike.
How to check it
- Run
/spark gcto inspect recent GC history; on versions that support it,/spark gcmonitorcan track upcoming collections. - For Java with unified logging, enable
-Xlog:gc*:file=gc.login the JVM startup flags, then restart during planned maintenance. - Reproduce lag and compare reported pauses (especially long stop-the-world phases) with spark tick spikes and player reports.
- Distinguish heap exhaustion, frequent short collections, infrequent long collections and non-GC CPU stalls. Consider allocation-heavy plugins and JVM/container memory limits.
- Keep before/after results with the same player count and workload; change one JVM or plugin variable at a time.
What to change
- Fix excessive object allocation or memory leaks identified in the relevant plugin or mod before adopting exotic JVM tuning presets.
- Keep enough RAM available for OS and native memory; do not allocate the entire machine to
-Xmx. - Prefer supported Java versions and known defaults; do not copy collector flags from unrelated software generations.
Software and version notes
Unified logging syntax and available collectors depend on the Java runtime. GC metrics may differ from overall heap use. A heap dump can contain private player or credential data; handle it securely.
Verify the result
- Compare GC pause frequency/duration, long-tick spikes and memory headroom under the same workload.
- Confirm the JVM completes stable restarts and does not encounter out-of-memory failures.
- If no pause aligns with lag, investigate tick CPU, chunk load, I/O and network instead.