Debugging artifact in jcmd:JDK14

Keywords: Programming Java jvm JDK Docker

brief introduction

Jcmd is the debugging tool that comes with JDK and has very powerful functions.Jcmd was officially introduced in JDK7. With jcmd, you can completely replace many other commonly used tools, such as jstak and jmap.

Jcmd can send specific diagnostic commands to the JVM.For security reasons, users using jcmd must have the same users and user groups as running java programs.

There are many debugging commands for jcmd, each of which has its own parameters.

This article will explain the use of jcmd in detail with specific examples.

Syntax for jcmd

The syntax of jcmd is simple:

jcmd [pid | main-class] command... | PerfCounter.print | -f filename

jcmd [-l]

jcmd -h

pid and main-class are two choices:

Where pid represents the java process id to send diagnostic commands.

You can also specify main-class, which means you want to send diagnostic commands to the java process running the main-class.

Commands represent commands that can be run in jcmd. Let's see which commands jcmd supports:

./jcmd 93989 help
93989:
The following commands are available:
Compiler.CodeHeap_Analytics
Compiler.codecache
Compiler.codelist
Compiler.directives_add
Compiler.directives_clear
Compiler.directives_print
Compiler.directives_remove
Compiler.queue
GC.class_histogram
GC.class_stats
GC.finalizer_info
GC.heap_dump
GC.heap_info
GC.run
GC.run_finalization
JFR.check
JFR.configure
JFR.dump
JFR.start
JFR.stop
JVMTI.agent_load
JVMTI.data_dump
ManagementAgent.start
ManagementAgent.start_local
ManagementAgent.status
ManagementAgent.stop
Thread.print
VM.class_hierarchy
VM.classloader_stats
VM.classloaders
VM.command_line
VM.dynlibs
VM.events
VM.flags
VM.info
VM.log
VM.metaspace
VM.native_memory
VM.print_touched_methods
VM.set_flag
VM.stringtable
VM.symboltable
VM.system_properties
VM.systemdictionary
VM.uptime
VM.version
help

Perfcounter.print indicates to print performance counters exposed by java processes.

-f filename means to read a command to run from a text file.

-l Lists JVM s that are not running in docker.

-h for help.

Here are a few common examples

List running JVM s

./jcmd -l
98109 jdk.jcmd/sun.tools.jcmd.JCmd -l

All running JVM processes can be listed by using jcmd-l.Same as jps.

Print stack information

Use jcmd PID Thread.print-l to print stack information for Java programs.Where -l represents the lock information of the output java.util.concurrent.

Here's a simple example:


./jcmd 93989 Thread.print -l

Full thread dump Java HotSpot(TM) 64-Bit Server VM (14.0.1+7 mixed mode, sharing):

Threads class SMR info:
_java_thread_list=0x00007fbeb1c4cb10, length=12, elements={
0x00007fbeb282a800, 0x00007fbeb282d800, 0x00007fbeb282e800, 0x00007fbeb2830800,
0x00007fbeb2831800, 0x00007fbeb2832000, 0x00007fbeb2833000, 0x00007fbeb3831000,
0x00007fbeb3822000, 0x00007fbeb3174000, 0x00007fbeb3815000, 0x00007fbeb226f800
}

"Reference Handler" #2 daemon prio=10 os_prio=31 cpu=0.64ms elapsed=8996.59s tid=0x00007fbeb282a800 nid=0x4703 waiting on condition  [0x000070000440d000]
   java.lang.Thread.State: RUNNABLE
	at java.lang.ref.Reference.waitForReferencePendingList(java.base@14.0.1/Native Method)
	at java.lang.ref.Reference.processPendingReferences(java.base@14.0.1/Reference.java:241)
	at java.lang.ref.Reference$ReferenceHandler.run(java.base@14.0.1/Reference.java:213)

   Locked ownable synchronizers:
	- None

Print heap info

heap info can be obtained using jcmd pid GC.heap_info.

./jcmd 93989 GC.heap_info
93989:
 garbage-first heap   total 71680K, used 34410K [0x00000007d4400000, 0x0000000800000000)
  region size 1024K, 20 young (20480K), 4 survivors (4096K)
 Metaspace       used 23810K, capacity 24246K, committed 24752K, reserved 1071104K
  class space    used 2850K, capacity 3015K, committed 3072K, reserved 1048576K

Print heap dump

If you want to know what's inside a heap, you can dump it out with the following command:

./jcmd 93989 GC.heap_dump heap_dump.out
93989:
Dumping heap to heap_dump.out ...
Heap dump file created [27727979 bytes in 0.643 secs]

heap dump needs to pass in a file name to store the dump's information.

Statistical heap usage

Sometimes we need to count the usage of each object in the heap by following these methods:

./jcmd 93989 GC.class_histogram

93989:
 num     #instances         #bytes  class name (module)
-------------------------------------------------------
   1:         25826       11748304  [B (java.base@14.0.1)
   2:          2233        1971800  [I (java.base@14.0.1)
   3:          5154         614928  java.lang.Class (java.base@14.0.1)
   4:         24757         594168  java.lang.String (java.base@14.0.1)
   5:          4491         439432  [Ljava.lang.Object; (java.base@14.0.1)
   6:         13177         421664  java.util.concurrent.ConcurrentHashMap$Node (java.base@14.0.1)
   7:          5025         160800  java.util.HashMap$Node (java.base@14.0.1)
   8:          8793         140688  java.lang.Object (java.base@14.0.1)
   9:           212         103584  [Ljava.util.concurrent.ConcurrentHashMap$Node; (java.base@14.0.1)

The above results are useful and can be unexpected in some performance debugging methods.

JFR function

jcmd also supports jfr functionality.The full name of JFR is called Java Flight Recorder.You can think of it as a logger for some events in the JVM.

More about JFR will be explained in more detail in my next article.

summary

jcmd has many other functions, you can use and explore more.

Author: Fldean Programs

Links to this article: http://www.flydean.com/jdk14-jcmd/

Source: Fldean's blog

Welcome to my Public Number: program stuff, more exciting waiting for you!

Posted by glassroof on Sun, 10 May 2020 15:57:28 -0700