Java 25 JVM options that still matter

JVM tuning advice ages quickly. Flags for PermGen, ParNew GC and the old PrintGCDetails logging system still appear in tutorials even though they no longer belong in a modern Java 25 configuration.

The best Java 25 JVM options are the ones that solve a specific operational problem. Start with JVM defaults, measure the application, and add flags only when you have a reason to change memory sizing, garbage collection, logging or diagnostics.

25 useful Java 25 JVM options

  1. -Xms sets the initial Java heap size.
  2. -Xmx sets the maximum Java heap size.
  3. -Xss sets the stack size for Java threads.
  4. -XX:InitialRAMPercentage sizes the initial heap as a percentage of available memory.
  5. -XX:MaxRAMPercentage sizes the maximum heap as a percentage of available memory.
  6. -XX:ActiveProcessorCount overrides the number of processors the JVM uses for sizing and ergonomics.
  7. -XX:+UseG1GC selects the G1 garbage collector.
  8. -XX:+UseZGC selects the low-latency Z Garbage Collector.
  9. -XX:+UseSerialGC selects Serial GC for small or constrained workloads.
  10. -XX:+UseParallelGC selects the throughput-oriented Parallel collector.
  11. -XX:MaxGCPauseMillis supplies a soft pause-time target to collectors such as G1.
  12. -XX:InitiatingHeapOccupancyPercent influences when concurrent collection work begins.
  13. -XX:+UseStringDeduplication allows supported collectors to deduplicate equivalent String backing data.
  14. -XX:+HeapDumpOnOutOfMemoryError writes a heap dump after an out-of-memory failure.
  15. -XX:HeapDumpPath controls where heap dumps are written.
  16. -XX:+ExitOnOutOfMemoryError terminates the JVM after an OutOfMemoryError.
  17. -XX:+CrashOnOutOfMemoryError forces a fatal JVM crash after an OutOfMemoryError.
  18. -Xlog:gc* enables detailed garbage-collection logging through unified JVM logging.
  19. -Xlog:safepoint logs JVM safepoint activity.
  20. -Xlog:class+load logs class loading.
  21. -XX:NativeMemoryTracking enables JVM native-memory accounting.
  22. -XX:StartFlightRecording starts Java Flight Recorder when the JVM starts.
  23. -XX:FlightRecorderOptions configures Java Flight Recorder behavior.
  24. -Duser.timezone defines the application's default JVM timezone.
  25. -Djava.library.path supplies locations for native libraries loaded by the JVM.

Heap sizing with Xms and Xmx

The two JVM options developers encounter most often are -Xms and -Xmx. This example starts with a 768 MB heap and permits it to grow to 2 GB:

java -Xms768m -Xmx2g -jar app.jar
Java JVM options

Modern JVM options let you control memory, garbage collection, diagnostics and runtime behavior.

Container-aware heap sizing

For containerized applications, percentage-based heap sizing is often more portable than hard-coding a heap size for every deployment.

java \
  -XX:InitialRAMPercentage=25 \
  -XX:MaxRAMPercentage=75 \
  -jar app.jar

The JVM derives its heap sizing from the memory available to the Java process. This is useful when the same image runs under different container memory limits.

Java 25 garbage collector options

Do not copy old collector flags such as -XX:+UseParNewGC into Java 25 command lines. Modern Java provides several supported collectors for different workload goals:

-XX:+UseG1GC
-XX:+UseZGC
-XX:+UseParallelGC
-XX:+UseSerialGC

G1 is a strong general-purpose collector. ZGC targets very low pause times and in modern JDK releases uses its generational implementation. Parallel GC emphasizes throughput, while Serial GC can be appropriate for very small heaps or constrained environments.

Modern GC logging with -Xlog

Legacy flags such as -XX:+PrintGCDetails, -XX:+PrintGCDateStamps and related print options have been replaced by the JVM's unified logging framework.

A practical Java 25 GC logging configuration is:

java \
  -Xlog:gc*:file=gc.log:time,uptime,level,tags \
  -jar app.jar

For interactive troubleshooting, you can send GC details directly to the console:

java -Xlog:gc* -jar app.jar

Heap dumps on OutOfMemoryError

For production troubleshooting, a heap dump can provide the evidence needed to find retained objects and memory leaks:

java \
  -XX:+HeapDumpOnOutOfMemoryError \
  -XX:HeapDumpPath=/var/log/myapp \
  -jar app.jar

Make sure the destination has enough free disk space and that heap dumps are handled securely because they can contain application data.

Java Flight Recorder

Java Flight Recorder is built into modern OpenJDK releases and is one of the most useful tools for low-overhead production diagnostics.

java \
  -XX:StartFlightRecording=filename=app.jfr,dumponexit=true \
  -jar app.jar

You can inspect the resulting recording with JDK Mission Control or the JDK's jfr command-line tool.

Native Memory Tracking

The Java heap is not the JVM's only consumer of memory. Native Memory Tracking helps investigate memory used by class metadata, threads, code caches and other JVM subsystems.

java -XX:NativeMemoryTracking=summary -jar app.jar

After the JVM starts, inspect native memory with jcmd:

jcmd <pid> VM.native_memory summary

Inspect Java 25 JVM flags

You can still ask HotSpot to display the final values of its JVM flags:

java -XX:+PrintFlagsFinal -version

This is useful when you need to see both explicitly configured values and values selected by JVM ergonomics.

Java 25 flags you should remove from old scripts

Several options found in older JVM tuning guides are obsolete or removed and should not be carried forward into Java 25 configurations:

  • -XX:PermSize and -XX:MaxPermSize, because PermGen was replaced by Metaspace long ago.
  • -XX:+UseParNewGC, an obsolete collector selection flag.
  • -XX:+PrintGCDetails and related legacy GC print flags, which have been superseded by unified -Xlog logging.
  • Old tuning recipes that manually size every young-generation region without first measuring the modern collector's behavior.

A sensible Java 25 production starting point

A production command line should remain intentionally small. For example:

java \
  -XX:MaxRAMPercentage=75 \
  -XX:+HeapDumpOnOutOfMemoryError \
  -XX:HeapDumpPath=/var/log/myapp \
  -Xlog:gc*:file=/var/log/myapp/gc.log:time,uptime,level,tags \
  -XX:StartFlightRecording=filename=/var/log/myapp/app.jfr,dumponexit=true \
  -jar app.jar

Do not treat a long JVM command line as proof of optimization. Java 25 has sophisticated runtime ergonomics. Start with defaults, collect measurements with JFR, GC logs and application metrics, and tune only the settings that address an observed problem.

Cameron McKenzie Cameron McKenzie is an AWS Certified AI Practitioner, Machine Learning Engineer, Solutions Architect and author of many popular books in the software development and Cloud Computing space. His growing YouTube channel training devs in Java, Spring, AI and ML has well over 30,000 subscribers.

Git, GitHub & GitHub Copilot Certification Made Easy

Want to get certified on the most popular AI, ML & DevOps technologies of the day? These five resources will help you get GitHub certified in a hurry.

Get certified in the latest AI, ML and DevOps technologies. Advance your career today.

Learn Git and GitHub fast!