Java Command a Developer Must Know

Why JVM Options Matter (Dev vs Production)

In development, we want fast feedback and simple defaults. In production, we care about:

  • Stable performance (low latency, predictable throughput)
  • Controlled memory usage (avoid OOM and excessive GC)
  • Observability (GC logs, heap dumps, JFR, JMX metrics)
  • Safe rollouts (repeatable flags, minimal risk)

JVM flags can make or break a system—especially under traffic spikes.


How to Pass JVM Options (Quick Examples)

Run a Java app with JVM flags

java -Xms512m -Xmx512m -jar app.jar

Spring Boot (recommended production layout)

Use JAVA_TOOL_OPTIONS or JAVA_OPTS in your service config:

export JAVA_TOOL_OPTIONS="-Xms512m -Xmx512m -XX:+UseG1GC"
java -jar app.jar

In Docker/Kubernetes (typical)

Use environment variable:

JAVA_TOOL_OPTIONS="-XX:MaxRAMPercentage=75 -XX:+UseG1GC"

Core Memory Options: -Xms and -Xmx

-Xms

Initial heap size.
Example:

-Xms512m

-Xmx

Maximum heap size.
Example:

-Xmx2g

Production best practices

  • For stable performance, many teams keep them equal: -Xms2g -Xmx2g This reduces heap resizing pauses and gives predictable GC behavior.
  • In containers, prefer percentage-based sizing: -XX:MaxRAMPercentage=75 -XX:InitialRAMPercentage=50 This plays better with Kubernetes memory limits.

Useful Memory & Diagnostics Flags

Print JVM flag values (helps confirm what’s really applied)

java -XX:+PrintFlagsFinal -version

Show VM settings

java -XshowSettings:vm -version
java -XshowSettings:system -version

Heap dump on OutOfMemoryError (production must-have)

-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/var/log/myapp/heapdumps

Exit on OOM (useful for auto-restart environments like K8s)

-XX:+ExitOnOutOfMemoryError

Garbage Collection (GC) Tuning: What to Use Today

Quick recommendation (most services)

For modern Java (11/17/21), G1GC is a safe default for most server apps:

-XX:+UseG1GC

Low-latency use cases

If you have strict latency SLOs and can test thoroughly:

  • ZGC (very low pauses, needs careful benchmarking) -XX:+UseZGC
  • Shenandoah (also low pause, depends on distribution)

Rule: pick a GC, then measure before tuning aggressively.


GC Logging (Production-grade)

GC logs are one of the best tools for diagnosing memory issues.

Java 9+ unified logging (recommended)

-Xlog:gc*,safepoint:file=/var/log/myapp/gc.log:time,level,tags:filecount=10,filesize=50M

What you learn from GC logs

  • GC frequency (too often = memory pressure)
  • Pause times (latency impact)
  • Promotion failures / allocation stalls
  • Old-gen growth (possible memory leak)

Common GC Tuning Flags (Use Carefully)

Target pause goal (G1)

-XX:MaxGCPauseMillis=200

This is a goal, not a guarantee.

Start GC earlier (G1) to avoid sudden long cycles

-XX:InitiatingHeapOccupancyPercent=30

Limit number of GC threads (sometimes useful in small CPUs)

-XX:ParallelGCThreads=4
-XX:ConcGCThreads=2

Tuning without load-testing is dangerous—always validate with realistic traffic.


Metaspace Tuning (Class metadata)

Metaspace stores class metadata (not part of heap).

-XX:MaxMetaspaceSize=256m

Be careful: setting it too low can cause OutOfMemoryError: Metaspace.


Thread Stack: -Xss

Controls stack size per thread.

-Xss512k
  • Smaller stack = you can run more threads
  • Too small = StackOverflowError risk

JMX (Java Management Extensions) for Monitoring

JMX lets you expose JVM and app metrics (threads, memory pools, GC, MBeans).

Local JMX (dev)

Usually no extra flags needed—tools like VisualVM or JConsole can attach locally.

Remote JMX (production – be careful!)

If you must use it, secure it properly (network policies + auth + TLS). Typical flags look like:

-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=9010
-Dcom.sun.management.jmxremote.rmi.port=9010
-Dcom.sun.management.jmxremote.authenticate=true
-Dcom.sun.management.jmxremote.ssl=true
-Djava.rmi.server.hostname=YOUR_HOSTNAME

Production guidance

  • Prefer Prometheus + JMX exporter or OpenTelemetry rather than opening remote JMX directly.
  • If opening remote JMX, restrict it with firewall/VPC/security groups.

JNLP (Java Web Start): What It Is (and Modern Reality)

JNLP was used to launch Java applications from browsers via Java Web Start.

Example old-style start:

javaws app.jnlp

Important (modern reality):

  • Oracle removed Java Web Start from the JDK long ago.
  • Today, if you still need JNLP-style launching, teams use alternatives like IcedTea-Web or migrate to packaged desktop apps (jpackage) or web apps.

So for “production-grade” in 2026, JNLP is usually legacy; include it only if you maintain older enterprise clients.


Troubleshooting Commands You Should Know

Check Java version + vendor

java -version

Find JVM process ID (PID)

jps -l

Print JVM command line flags used by a running process

jcmd <pid> VM.command_line

Thread dump (when app is stuck / high CPU)

jstack <pid> > threaddump.txt

Or safer in production:

jcmd <pid> Thread.print > threaddump.txt

Heap histogram (who uses memory)

jcmd <pid> GC.class_histogram > histo.txt

Trigger heap dump (investigation)

jcmd <pid> GC.heap_dump /var/log/myapp/heap.hprof

Production-Ready JVM Flag Templates

1) Standard microservice (Java 17/21, G1GC, observability)

JAVA_TOOL_OPTIONS="
-XX:+UseG1GC
-XX:MaxRAMPercentage=75
-XX:InitialRAMPercentage=50
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/var/log/myapp/heapdumps
-XX:+ExitOnOutOfMemoryError
-Xlog:gc*,safepoint:file=/var/log/myapp/gc.log:time,level,tags:filecount=10,filesize=50M
"

2) Fixed heap (VM-based deployment, predictable behavior)

JAVA_TOOL_OPTIONS="
-Xms2g -Xmx2g
-XX:+UseG1GC
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/var/log/myapp/heapdumps
-Xlog:gc*:file=/var/log/myapp/gc.log:time,level,tags
"

3) Low-latency experiment (requires benchmarking)

JAVA_TOOL_OPTIONS="
-XX:+UseZGC
-XX:MaxRAMPercentage=75
-Xlog:gc*:file=/var/log/myapp/gc.log:time,level,tags
"

A Simple Tuning Checklist (Practical)

  1. Set container memory limits (or VM RAM) correctly.
  2. Choose heap strategy:
    • Fixed: -Xms = -Xmx (stable)
    • Container aware: MaxRAMPercentage
  3. Enable GC logs + heap dump on OOM.
  4. Watch:
    • GC frequency, pause times, old-gen growth
    • CPU usage, thread counts, allocation rate
  5. Only then tune:
    • G1 pause goals, IHOP, thread counts, metaspace caps
  6. Validate changes using load testing and compare before/after.

FAQ

Should I always set -Xms equal to -Xmx?

Often yes for server workloads, but in containers percentage-based settings can be more flexible.

Is GC tuning mandatory?

No. Good observability is mandatory. Tuning is optional unless you see a real problem.

Is JMX safe in production?

Only if secured. Prefer metrics exporters/telemetry rather than exposed remote ports.

Is JNLP still used?

Mostly legacy. For modern desktop deployments, consider jpackage or a web-based approach.


Conclusion

For production-grade Java, the most impactful “commands” are not exotic GC flags—it’s getting the basics right:

  • sensible heap sizing (-Xms/-Xmx or RAM percentages),
  • GC logs,
  • heap dumps on OOM,
  • safe observability (JMX exporter / telemetry),
  • and measuring under real load.