欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

深入浅析jcmd:JDK14中的调试神器

程序员文章站 2022-03-20 13:43:34
jcmd是jdk自带的调试工具,具有非常强大的功能。jcmd是jdk7中正式引入的,有了jcmd,完全可以替换很多常用的其他工具,比如jstak和jmap。jcmd可以将具体的诊断命令发送给jvm。为...

jcmd是jdk自带的调试工具,具有非常强大的功能。jcmd是jdk7中正式引入的,有了jcmd,完全可以替换很多常用的其他工具,比如jstak和jmap。

jcmd可以将具体的诊断命令发送给jvm。为了安全起见,使用jcmd的用户必须跟运行的java程序具有同样的用户和用户组。

jcmd的调试命令有很多种,每一种调试命令又有自己的参数。

本文将会结合具体的例子详细讲解jcmd的使用。

jcmd的语法

jcmd的语法比较简单:

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

jcmd [-l]

jcmd -h

pid和main-class是二选一:

其中pid表示要发送诊断命令的java进程id。

也可以指定main-class,表示要发送诊断命令给运行该main-class的java进程。

command表示可以在jcmd中运行的命令,我们看下jcmd支持哪些命令:

./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表示要打印java进程暴露的performance counters。

-f filename表示从文本文件中读取要运行的命令。

-l 列出不是运行在docker中jvm。

-h 表示帮助。

下面我们举几个常用的例子

列出运行的jvm

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

通过使用jcmd -l可以列出所有正在运行的jvm进程。跟jps是一样的。

打印stack信息

使用jcmd pid thread.print -l可以打印出java程序的stack信息。其中-l表示输出java.util.concurrent的lock信息。

下面看个简单的例子:

./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

打印heap info

使用jcmd pid gc.heap_info可以获得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

打印heap dump

如果想知道heap里面到底有什么,则可以通过下面的命令将heap dump出来:

./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需要传入一个文件名,存放dump出来的信息。

统计heap使用情况

有时候我们需要统计一下heap中各个对象的使用情况,则可以下面方法:

./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)

上面的结果非常有用,在一些性能调试方法可以起到意想不到的作用。

jfr功能

jcmd还支持jfr功能。jfr的全称叫做java flight recorder。你可以将其看做是jvm中一些事件的记录器。

有关jfr的更多内容,可以点击查阅:

到此这篇关于深入浅析jcmd:jdk14中的调试神器的文章就介绍到这了,更多相关jcmd:jdk14调试神器内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!