7 minutes read

If you need to configure various aspects of the JVM, or you want to deepen your knowledge in learning Java, JVM options are a must. In this topic, you will get to learn about all sorts of options, how to use them in practice and what impact they will have on our application. Let's get started!

The general structure of options

What are JVM options? They allow configuring parameters of JVM and are usually specified at the JVM startup.
Some of them are static and set at the JVM startup, which means they can't be overridden at runtime. Others are manageable: you can update them during runtime. To set an option you can use these two structures:

  • java [options] classname [args]

  • java [options] -jar filename [args]

Here [options] means single or multiple options. If several options are passed, they should be separated by spaces.

Standard options

Standard options are supported by all JVM implementations. Most of them affect the application runtime, except for those that show a version or some documentation for the java command. Standard options allow you to launch the application, set up an environment, and use some Java APIs.

As an example, we'll write a simple program that prints out "Hello, world!".

public class Main {
    public static void main(String[] args) {
        System.out.println("Hello, world!");
    }
}

Standard options start with - as well.

Here is a couple of examples:

  • -verbose:gc: this is the command to enable displaying output about every garbage collection event.

java -verbose:gc Main
  • -verbose:class: will show information about each loaded class

java -verbose:class Main

System properties

One of the most popular ways of customizing a program is setting system properties. The syntax is simple:

  • -D<property_name>=<property_value>: sets a system property value.

java -Dfile.encoding=UTF-8 Main

Here, D means "define" and specifies that the given option is a user-defined one. The file.encoding property is responsible for the current character encoding (by default JVM uses UTF-8). Let's add the code to our program and check the current encoding:

public class Main {
    public static void main(String[] args) {
        System.out.println("Hello, world!");
        String currentUTF = System.getProperty("file.encoding"); // Gets the system property 
        System.out.println(currentUTF); // UTF-8
    }
}

Now, let's change the encoding to UTF-32 using the following option:

java -Dfile.encoding=UTF-32 Main

The program should output the following text:

Hello, world!
UTF-32

We can also create our own option. For instance, passing "Manual" as a mode parameter:

  • -Dmode=Manual

In Java, we could use it like this:

String mode = System.getProperty("mode");  // Manual

Non-standard options

Non-standard options start with -X, where X stands for extension. Unlike standard options, they are not guaranteed to be supported by all JVM implementations. They can change the mode of runtime compilation, enable profiling, use CDS, and set heap size.

There are non-standard options that accept size parameters by default. They expect a value in bytes, but you can add k or K for kilobytes, m or M for megabytes, and g or G for gigabytes. Options that accept percentage parameters expect a value from 0 to 1, where 0.5 is 50 %.

Here are a few examples:

  • -Xss<size>: sets the size of the thread stack.

java -Xss4096k Main
  • -Xcomp: sets the mode in which all methods will be compiled on the first invocation (by default, the method compiles only after a large number of invocations).

java -Xcomp Main

Advanced runtime

Advanced options start with -XX. They can have a significant impact on application performance, so don't use them in a production environment without a full understanding of the consequences. Among them are the so-called boolean options or flags.

Flags are boolean options without values. At the same time, flags are often used as a synonym for options.

In that case, after -XX you can put + or - to enable or disable an option. With these options, you can control things like using Java Flight Recorder (JFR) or configure memory alignment of Java objects.

Here is an example:

-XX:+PrintCommandLineFlags: enables the printing of ergonomically selected JVM options. It might be helpful to know the default values chosen by JVM.

java -XX:+PrintCommandLineFlags Main

Advanced JIT compiler

These options control just-in-time compilation. Some options enable additional logging JIT events, and other configure the compiler itself.

Here are some examples:

  • -XX:+PrintCompilation: enables the printing of every compiled method:

java -XX:+PrintCompilation Main
  • XX:+PrintInlining: enables the printing of inlining decisions made by JIT. For using this flag, use -XX:+UnlockDiagnosticVMOptions:

java -XX:+UnlockDiagnosticVMOptions -XX:+PrintInlining Main

Ahead-of-time class loading and linking

A new feature introduced in Java 24 allows the JVM to load and link classes ahead of time to significantly reduce application startup time. This feature, defined in JEP 483, works by recording class-loading behavior during a training run and storing it in a cache, which can then be reused in future runs.

This approach is particularly useful for large applications that start up the same way each time. It works seamlessly with existing Java applications and frameworks and requires no changes to your code.

The process involves three main steps:

  1. Record class usage during a training run:

    java -XX:AOTMode=record -XX:AOTConfiguration=app.aotconf -cp app.jar com.example.App

    This generates a configuration file (app.aotconf) that tracks which classes are loaded.

  2. Create the AOT cache:

    java -XX:AOTMode=create -XX:AOTConfiguration=app.aotconf -XX:AOTCache=app.aot -cp app.jar

    This step processes the recorded configuration and generates the cache file (app.aot).

  3. Run the application using the AOT cache:

    java -XX:AOTCache=app.aot -cp app.jar com.example.App

    The JVM will now load and link classes from the cache, reducing startup time.

If the cache is missing or unusable, the JVM prints a warning and continues execution normally. For strict checking, you can add:

java -XX:AOTCache=app.aot -XX:AOTMode=on -cp app.jar com.example.App

This causes the JVM to fail fast if any requirements for cache use are violated (e.g., inconsistent classpath or module settings).

If needed, you can disable the AOT cache entirely:

java -XX:AOTMode=off -cp app.jar com.example.App

This prevents the JVM from using any AOT cache, even if one is specified.

You can also let the JVM decide:

java -XX:AOTMode=auto -XX:AOTCache=app.aot -cp app.jar com.example.App

This is the default mode: the JVM attempts to use the AOT cache but will fall back to regular class loading if the cache is invalid or missing.

This feature builds upon the existing Class Data Sharing (CDS) mechanism but goes further by also linking classes ahead of time.

Keep in mind:

  • Only classes loaded by the JVM’s built-in class loaders can be cached (e.g., from the class path or module path).

  • Class path, JDK version, and module settings must remain consistent between training and production runs.

  • Z Garbage Collector (ZGC) is not yet supported.

This Java 24 feature lays the groundwork for future improvements to both startup and warmup performance.

Advanced serviceability

These options provide the capability to gather system information and perform extensive debugging. They allow to set up heap dumping, specify the log file name, print class instance histogram or concurrent locks after a Control+Break event.

Here is an example:

  • -XX:LogFile=path: sets the log file where log data is written:

java -XX:LogFile=C:/JVM/logfile.log Main

Advanced garbage collection

These options control how garbage collection is performed by the JVM. With them, you can enable some optimizations, choose a garbage collector implementation, and configure the heap.

Here are a couple of examples:

  • -XX:+UseSerialGC: enables the use of the serial garbage collector:

java -XX:+UseSerialGC Main
  • -XX:+UseStringDeduplication: enables the use of string deduplication. It can noticeably reduce memory usage by String objects if your app has a lot of identical strings:

java -XX:+UseStringDeduplication Main

This option is available for the G1 garbage collector.

Conclusion

Options help configure various aspects of JVM: garbage collection, logging, serviceability, and many more. Some options are shared between different implementations, while others can exist only for certain JVM or even have different behavior.

Remember that options can become deprecated and be removed from the newest versions of JDK. So you might want to develop the habit of reading the release notes before updating to the newer JDK version.

57 learners liked this piece of theory. 1 didn't like it. What about you?
Report a typo