Imagine a situation when you observe a memory leak in production java application, and with increasing memory usages you know it can throw OutOfMemoryError in some time. You have not set HeapDumpOnOutOfMemoryError and HeapDumpPath flags while starting the Java application. This being your production application, now you can not restart application immediately and set these flags. In such a situation jinfo
can be great help, it can help us to set these flags for a running Java application. We will see this particular example later in the post.
While troubleshooting production Java application often we need to check command line flags passed to JVM, arguments passed to the main function, and system properties. jinfo
is a very helpful command to get this information.
Troubleshooting a Java Application with jinfo
In this section, we will see how to use jinfo
with a running Java process.
Command structure
jinfo [option] pid
option: This represents the jinfo command-line options, we will how to use these options later in this post.
pid: The process ID for which the configuration information is to be printed.
Java program we will be analyzing in this post
Following is Java class we will run to understand different features available in jinfo
public class Test
{
public static void main(String[] args)
{
while(true)
{
}
}
}
For all our examples we will be using Java 17, as of writing this post it is built using JDK master branch. This post can help you to build JDK from source.
We are running Java process using below command:
java -XX:ConcGCThreads=6 -Xmx256m -Xms8m -Xss256k -DTEST_ARGUMENT=1 Test argument1 argument2
This command prints java process ids, see this blog post to read more about jps
.
jps -ml
Output:
10000 Test argument1 argument2
10071 jdk.jcmd/sun.tools.jcmd.JCmd -l
pid 10000 is the java process we will use in rest of the post.
jinfo help command
This is jinfo
help command, it prints usage instructions and all the options available in jinfo
jinfo --help
Output of help command:
Usage:
jinfo <option> <pid>
(to connect to a running process)
where <option> is one of:
-flag <name> to print the value of the named VM flag
-flag [+|-]<name> to enable or disable the named VM flag
-flag <name>=<value> to set the named VM flag to the given value
-flags to print VM flags
-sysprops to print Java system properties
<no option> to print both VM flags and system properties
-? | -h | --help | -help to print this help message
Print command-line flags passed to the JVM
This command prints command-line flags passed to the JVM
jinfo -flags 10000
Output:
VM Flags:
-XX:CICompilerCount=12 -XX:ConcGCThreads=3 -XX:G1ConcRefinementThreads=13 -XX:G1HeapRegionSize=8388608 -XX:GCDrainStackTargetSize=64 -XX:InitialHeapSize=788529152 -XX:MarkStackSize=4194304 -XX:MaxHeapSize=12616466432 -XX:MaxNewSize=7566524416 -XX:MinHeapDeltaBytes=8388608 -XX:MinHeapSize=8388608 -XX:NonNMethodCodeHeapSize=7602480 -XX:NonProfiledCodeHeapSize=122027880 -XX:ProfiledCodeHeapSize=122027880 -XX:ReservedCodeCacheSize=251658240 -XX:+SegmentedCodeCache -XX:SoftMaxHeapSize=12616466432 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps -XX:+UseG1GC
Print a particular command-line flag in running Java process
This command prints value of a particular flag UseG1GC:
jinfo -flag UseG1GC 10000
Output:
-XX:+UseG1GC
Another example to print flag CICompilerCount
jinfo -flag CICompilerCount 10000
Output:
-XX:CICompilerCount=12
Print Java system properties as name-value pairs
This command prints system properties:
jinfo -sysprops 10000
Output:
Java System Properties:
#Sun Jun 27 11:02:17 IST 2021
java.specification.version=17
sun.management.compiler=HotSpot 64-Bit Tiered Compilers
sun.jnu.encoding=UTF-8
java.runtime.version=17-internal+0-adhoc.vipin.jdk
...
...
Printing all 3, system properties, VM flags, and VM arguments
This is jinfo
command to print system properties, VM flags, and VM arguments:
jinfo 10000
Output:
Java System Properties:
#Sun Jun 27 11:02:17 IST 2021
java.specification.version=17
sun.management.compiler=HotSpot 64-Bit Tiered Compilers
sun.jnu.encoding=UTF-8
java.runtime.version=17-internal+0-adhoc.vipin.jdk
...
VM Flags:
-XX:CICompilerCount=12 -XX:ConcGCThreads=6 -XX:G1ConcRefinementThreads=13 -XX:G1HeapRegionSize=1048576 -XX:GCDrainStackTargetSize=64 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/home/vipin -XX:InitialHeapSize=8388608 -XX:MarkStackSize=4194304 -XX:MaxHeapSize=268435456 -XX:MaxNewSize=160432128 -XX:MinHeapDeltaBytes=1048576 -XX:MinHeapSize=8388608 -XX:NonNMethodCodeHeapSize=7602480 -XX:NonProfiledCodeHeapSize=122027880 -XX:ProfiledCodeHeapSize=122027880 -XX:ReservedCodeCacheSize=251658240 -XX:+SegmentedCodeCache -XX:SoftMaxHeapSize=268435456 -XX:ThreadStackSize=256 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps -XX:+UseG1GC
VM Arguments:
jvm_args: -XX:ConcGCThreads=6 -Xmx256m -Xms8m -Xss256k -DTEST_ARGUMENT=1
java_command: Test argument1 argument2
java_class_path (initial): .
Launcher Type: SUN_STANDARD
Update manageable VM flags
jinfo
can update manageable VM flags for a running Java application. While starting our Java application if we have not set HeapDumpOnOutOfMemoryError and HeapDumpPath flags, we can set these with jinfo
.
This is the command to find all manageable flags, that can be updated for a running Java application.
jcmd 10000 VM.flags -all | grep manageable
Output:
uintx G1PeriodicGCInterval = 0 {manageable} {default}
double G1PeriodicGCSystemLoadThreshold = 0.000000 {manageable} {default}
bool HeapDumpAfterFullGC = false {manageable} {default}
bool HeapDumpBeforeFullGC = false {manageable} {default}
intx HeapDumpGzipLevel = 0 {manageable} {default}
bool HeapDumpOnOutOfMemoryError = false {manageable} {default}
ccstr HeapDumpPath = {manageable} {default}
uintx MaxHeapFreeRatio = 70 {manageable} {default}
uintx MinHeapFreeRatio = 40 {manageable} {default}
bool PrintClassHistogram = false {manageable} {default}
bool PrintConcurrentLocks = false {manageable} {default}
bool ShowCodeDetailsInExceptionMessages = true {manageable} {default}
size_t SoftMaxHeapSize = 268435456 {manageable} {ergonomic}
These are commands to update heap dump related flags:
jinfo -flag HeapDumpOnOutOfMemoryError=true 10000
jinfo -flag HeapDumpPath=/home/vipin 10000
Let’s check all flag values again, we can see HeapDumpOnOutOfMemoryError is true, and HeapDumpPath is set now.
$ jcmd 10000 VM.flags -all | grep manageable
uintx G1PeriodicGCInterval = 0 {manageable} {default}
double G1PeriodicGCSystemLoadThreshold = 0.000000 {manageable} {default}
bool HeapDumpAfterFullGC = false {manageable} {default}
bool HeapDumpBeforeFullGC = false {manageable} {default}
intx HeapDumpGzipLevel = 0 {manageable} {default}
bool HeapDumpOnOutOfMemoryError = true {manageable} {default}
ccstr HeapDumpPath = /home/vipin {manageable} {attach}
uintx MaxHeapFreeRatio = 70 {manageable} {default}
uintx MinHeapFreeRatio = 40 {manageable} {default}
bool PrintClassHistogram = false {manageable} {default}
bool PrintConcurrentLocks = false {manageable} {default}
bool ShowCodeDetailsInExceptionMessages = true {manageable} {default}
size_t SoftMaxHeapSize = 268435456 {manageable} {ergonomic}
Conclusion
jinfo
is a very useful command to check VM flags, system properties and even we can set value of some VM flags. Utilities like this are very useful in a situation when we need to analyze and resolve problems in production Java application quickly. jinfo
is part of JDK itself, no need to install any third party software.
If you want to get amazing Java jobs, I wrote an ebook 5 steps to Best Java Jobs. You can download this step-by-step guide for free!