by Patrick Peschlow

With a recent update of Java 6 (must have been update 20 oder 21), the HotSpot JVM offers two new command line flags which print a table of all XX flags and their values to the command line right after JVM startup. As many HotSpot users were longing for such a feature since the first versions of Java, I decided to make it the main topic of this article.

-XX:+PrintFlagsFinal and -XX:+PrintFlagsInitial

Let us take a look at the output of the new flags right away. Starting the client VM using -XX:+PrintFlagsFinal results in an alphabetically sorted table of 590 XX flags (note that the number of flags may change with each release):

$ java -client -XX:+PrintFlagsFinal Benchmark [ Global flags ] uintx AdaptivePermSizeWeight = 20 { product } uintx AdaptiveSizeDecrementScaleFactor = 4 { product } uintx AdaptiveSizeMajorGCDecayTimeScale = 10 { product } uintx AdaptiveSizePausePolicy = 0 { product } [ ... ] uintx YoungGenerationSizeSupplementDecay = 8 { product } uintx YoungPLABSize = 4096 { product } bool ZeroTLAB = false { product } intx hashCode = 0 { product } $ java -client -XX:+PrintFlagsFinal Benchmark [Global flags] uintx AdaptivePermSizeWeight = 20 {product} uintx AdaptiveSizeDecrementScaleFactor = 4 {product} uintx AdaptiveSizeMajorGCDecayTimeScale = 10 {product} uintx AdaptiveSizePausePolicy = 0 {product} [...] uintx YoungGenerationSizeSupplementDecay = 8 {product} uintx YoungPLABSize = 4096 {product} bool ZeroTLAB = false {product} intx hashCode = 0 {product}

Each table row represents an XX flag and contains five columns. The first column shows the data type of the flag, the second one its name, the fourth one its value, and the fifth one its category. In the third column, “=” means that the value in column 4 is the default value for the flag, while “:=” indicates that the flag was set to that value (either by the user or by JVM ergonomics).

Note that I am only using the “Benchmark” class for this example because it was used in the previous parts of this series as well. You can get the same output even without a main class by running java with the additional parameter -version .

Now let us check how many flags the server VM offers. In order to unlock any additional hidden flags, we also specify the flags -XX:+UnlockExperimentalVMOptions and -XX:+UnlockDiagnosticVMOptions :

$ java -server -XX:+UnlockExperimentalVMOptions -XX:+UnlockDiagnosticVMOptions -XX:+PrintFlagsFinal Benchmark $ java -server -XX:+UnlockExperimentalVMOptions -XX:+UnlockDiagnosticVMOptions -XX:+PrintFlagsFinal Benchmark

The result is a whopping 724 flags. Wow! Let us take a look at the flags that have been set to values other than the default:

$ java -server -XX:+UnlockExperimentalVMOptions -XX:+UnlockDiagnosticVMOptions -XX:+PrintFlagsFinal Benchmark | grep ":" uintx InitialHeapSize := 57505088 { product } uintx MaxHeapSize := 920649728 { product } uintx ParallelGCThreads := 4 { product } bool PrintFlagsFinal := true { product } bool UseParallelGC := true { product } $ java -server -XX:+UnlockExperimentalVMOptions -XX:+UnlockDiagnosticVMOptions -XX:+PrintFlagsFinal Benchmark | grep ":" uintx InitialHeapSize := 57505088 {product} uintx MaxHeapSize := 920649728 {product} uintx ParallelGCThreads := 4 {product} bool PrintFlagsFinal := true {product} bool UseParallelGC := true {product}

We have only set one of the flags, -XX:+PrintFlagsFinal , ourselves. The other flags were set by the server VM based on the underlying system, in order to run with appropriate heap size and garbage collector settings.

If we only want to see the default values of all XX flags, we can use a related flag, -XX:+PrintFlagsInitial . With -XX:+PrintFlagsInitial , the output only shows the original “=” entries in column 3 (also for those flags that were set to other values). However, note that some of the flags are missing when compared to the output of -XX:+PrintFlagsFinal , supposedly because these flags are created dynamically.

It is interesting to study the table contents in order to compare the behavior of the client and the server VM. Also, it is revealing to see which flags affect the values of other flags when being set on the command line. For the interested reader, such a study is described in the excellent blog post Inspecting HotSpot JVM Options. This post also briefly explains the meaning of the flag categories shown in column 5.

-XX:+PrintCommandLineFlags

To conclude the topic, let us consider one more flag which in fact has been available for quite some time already: -XX:+PrintCommandLineFlags . This flag tells the JVM to print the names and values of exactly those XX flags that have been set by the user or JVM ergonomics on startup. In other words, it lists the flags that have a “:=” in column 3 of the -XX:+PrintFlagsFinal output. Seen this way, we may consider -XX:+PrintCommandLineFlags as a shortcut to use when we are only interested in the modified flags. Let us return to the above example:

$ java -server -XX:+PrintCommandLineFlags Benchmark -XX: InitialHeapSize = 57505088 -XX: MaxHeapSize = 920081408 -XX: ParallelGCThreads = 4 -XX:+PrintCommandLineFlags -XX:+UseParallelGC $ java -server -XX:+PrintCommandLineFlags Benchmark -XX:InitialHeapSize=57505088 -XX:MaxHeapSize=920081408 -XX:ParallelGCThreads=4 -XX:+PrintCommandLineFlags -XX:+UseParallelGC

Now if we set -XX:+PrintCommandLineFlags every time we start a Java program and write its output to a log file, we document the effects of our JVM flag settings on the performance of the application. Thus, similar to -showversion (see part 1 of this series), I consider -XX:+PrintCommandLineFlags a flag that should always be set on JVM startup. It comes for free, and you never know when you are going to need that information.