3 JVM Parameters You Must Know

When you’re running a Java application in production, performance often comes down to how you configure memory. And by “memory,” I mean how the JVM handles it—not just how much RAM your machine has.

It’s easy to launch a Spring Boot app with a java -jar, but if you’re not passing the right flags, you’re leaving performance—and stability—on the table. Here are three JVM parameters you absolutely should understand and configure.

1. Heap Size: Control the Playground

At the core of every Java app is the heap: the memory space where objects live. If you don’t set boundaries here, the JVM will guess for you. Spoiler: it usually guesses wrong.

-Xms512m   # Initial heap size
-Xmx2048m  # Maximum heap size

Why it matters?

  • Too low: frequent garbage collection, high CPU usage, poor throughput.
  • Too high: memory bloat, long GC pauses, possibly OOM if the host runs out of physical RAM.

My approach? Always set -Xms and -Xmx to the same value in production. This avoids heap resizing and keeps performance consistent.

2. Out of Memory Handling: Prepare for Failure

Let’s be honest, at some point, your app will run out of memory. Either due to a memory leak, an unexpected load spike, or just bad luck. The worst thing you can do is be unprepared for it.

-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/var/log/app/heapdump.hprof
-XX:+ExitOnOutOfMemoryError

Why it matters?

  • HeapDumpOnOutOfMemoryError lets you inspect what filled up the memory.
  • HeapDumpPath gives you control over where the file lands (and avoids polluting your working directory).
  • ExitOnOutOfMemoryError ensures the process exits cleanly, allowing orchestration tools (e.g., Kubernetes) to restart it.

It’s not about avoiding memory issues entirely—it’s about making sure they don’t take down your entire system unnoticed.

3. Garbage Collector: Pick the Right Cleaner

The GC is the JVM’s janitor. And like any janitor, how fast and efficient it works depends on the tools you give it. Not all collectors are created equal, and using the default may not be optimal for your use case.

-XX:+UseG1GC        # Balanced throughput + low pause
-XX:+UseZGC         # Ultra-low pause, modern hardware
-XX:+UseParallelGC  # High throughput, batch workloads

Choosing the right one:

  • G1GC: Good general-purpose GC. I use it for most web apps.
  • ZGC: Great for apps that require ultra-low latency. But needs a modern JDK (15+).
  • ParallelGC: Effective for batch jobs or apps where pause time is less critical.

Test in your environment. GC behavior is deeply tied to your object lifecycle, hardware, and workload patterns.

It’s All in the Flags

Every JVM option covered here can—and should—be passed via command-line when launching your app:

java -Xms512m -Xmx2048m \
     -XX:+HeapDumpOnOutOfMemoryError \
     -XX:HeapDumpPath=/var/log/app/heapdump.hprof \
     -XX:+ExitOnOutOfMemoryError \
     -XX:+UseG1GC \
     -jar app.jar

These three areas—heap sizing, memory error handling, and GC choice—are low-hanging fruit. Configure them properly, and your JVM will behave much more predictably under pressure.


Never Miss Another Tech Innovation

Concrete insights and actionable resources delivered straight to your inbox to boost your developer career.

My New ebook, Best Practices To Create A Backend With Spring Boot 3, is available now.

Best practices to create a backend with Spring Boot 3

Leave a comment

Discover more from The Dev World - Sergio Lema

Subscribe now to keep reading and get access to the full archive.

Continue reading