Project Zomboid Field guide

Project Zomboid server memory: fix the right limit before raising Xmx

Distinguish Java heap errors, whole-process memory and Linux OOM when diagnosing a Project Zomboid server.

Project Zomboid server memory: fix the right limit before raising Xmx

OutOfMemoryError: Java heap space and a server that disappears with Killed need different checks. The first identifies a Java heap allocation failure; the second needs evidence from Linux or the container supervisor. Increasing -Xmx without identifying the limit can make a server stop sooner.

This guide covers Linux dedicated servers. The current Stable build is 42.21 on 26 October 2026. It also applies to the diagnostic process for retained older servers, but their launchers and supplied Java runtime can differ. Keep the runtime shipped with the selected server build; installing another system Java is not a memory adjustment.

Read the failure before changing the allocation#

Save the relevant game log and the supervisor's exit report from the same time window. Look for the complete error, not just a disconnected client:

ObservationWhat to inspect next
OutOfMemoryError: Java heap spaceEffective heap ceiling, recent workload and mod changes
Native allocation failure or an hs_err_pid reportProcess memory, available host/container budget, native libraries and threads
Killed, exit 137 or signal 9Kernel OOM messages and container memory events; these symptoms alone do not prove OOM
Failure to reserve memory at startupStarting heap, maximum heap, address-space or service limits
Only the player's client crashesThat client's log and launcher; a server heap change may be irrelevant

Read the line preceding the exception too. A missing mod, incompatible save or permission error is not repaired by adding RAM. If the kernel killed the process, preserve the stopped world before repeated startup attempts; use a complete server backup.

Find the launcher that actually starts the dedicated server#

The Steam game client and the dedicated-server tool have separate installations. Editing the client's ProjectZomboid64.json will not configure a remote server. The in-game Host memory selector is another launch path.

For a Linux package whose start-server.sh launches the native ProjectZomboid64 launcher, heap options normally come from vmArgs in the adjacent server-side ProjectZomboid64.json. Check the real startup script and startup output: if a wrapper runs Java directly, its own argument list may be authoritative instead. Windows packages may invoke bundled Java from StartServer64.bat; do not transplant that file into Linux.

A panel or container entrypoint can rewrite the JSON at every start. For example, the maintained indifferentbroccoli image sets it from MEMORY_XMX_GB and optional MEMORY_XMS_GB. Those are settings of that particular image. Use your image's documented configuration rather than adding similarly named variables to an unrelated installation.

Keep a copy of the original launcher configuration. Confirm the dedicated installation path and leave its classpath, native-library paths and bundled runtime intact.

Compare three different measurements#

-Xmx is the heap ceiling, not the maximum memory of the entire server process. -Xms controls the starting heap. Native allocations, thread stacks and other JVM areas need memory outside that heap. RSS describes resident process pages; a large VSZ includes virtual address space and does not by itself show that physical RAM is exhausted.

On the Linux host, replace 12345 with the verified game process PID, not the shell wrapper's PID:

bash
PZ_PID=12345
ps -p "$PZ_PID" -o pid,rss,vsz,etime,comm
readlink -f "/proc/$PZ_PID/cwd"
cat "/proc/$PZ_PID/cgroup"
free -h
journalctl -k --since '30 minutes ago' --no-pager

RSS and VSZ from this ps output are in KiB. Kernel logs may require administrator permission. Correlate an OOM-kill record with the game PID and incident time; an unrelated kill is not evidence about this instance.

On cgroup v2, identify the game's actual cgroup from that process and inspect its memory.current, memory.max and memory.events files in the mounted hierarchy. Record oom_kill before and after the incident. Check ancestor limits too. A container can run out of its own allowance while the host still has free RAM. Do not assume /sys/fs/cgroup inside an arbitrary shell belongs to the game, especially across container namespaces.

Identify the failure and effective limits before changing one setting, then repeat a comparable workload.

Change one setting with measurable headroom#

For confirmed heap exhaustion, increase the ceiling only if the effective allowance has room for the larger process. As an illustrative starting experiment, a server with an exclusive 12 GiB allowance might use -Xmx6g; this is neither a game requirement nor a player-capacity promise. Measure its actual busy-session usage before deciding on the next value.

If native allocation or cgroup pressure is the problem, a larger heap may reduce the remaining headroom. Consider a lower heap, fewer competing processes or a larger allowance after measuring the cause. Do not force -Xms equal to the entire host RAM. Check that an existing starting heap is not larger than the new maximum.

With the server saved and stopped, edit the existing -Xmx entry inside the authoritative JSON's vmArgs array. For the example above, that single JSON string is:

json
"-Xmx6g"

Preserve the surrounding file and ensure there is only one intended maximum-heap setting. Use the size suffix: -Xmx6 does not mean six gigabytes. If the wrapper owns the value, change its source setting instead.

Verify the next launch and a representative session#

Start normally and inspect the fresh startup output for the selected config file and vmArg heap value. A native launcher may read JSON without putting those options in /proc/PID/cmdline; their absence there does not prove they were ignored. If the launcher omits flag diagnostics, use an available compatible JVM inspection tool or the wrapper's documented diagnostics. A file edit alone is not verification.

Join, explore the areas that triggered the failure and repeat the relevant player/mod workload. Record the heap setting, RSS, cgroup usage and errors over time, then save, stop and restart once more. If usage keeps growing under a comparable load, investigate the game build or mod change on a separate copy rather than increasing the ceiling indefinitely. Never remove content mods from the only production save as an experiment.

When administering your own machines through Nexardo, keep both the infrastructure allowance and the game's effective heap in the change record. Recheck the launcher after updates: package validation or an entrypoint can replace a manual edit.

Sources#