一、jcmd
jcmd的作用是发送诊断命令请求到正在运行的Java虚拟机(JVM),打印出java进程运行和性能相关的信息,它必须和JVM运行在同一台机器上,并且与启动JVM用户具有相同的组权限。
灵活使用jcmd可以快速获得运行的java进程相关的信息,例如性能数据、参数、heapdump、threaddump等,非常方便,堪称利器。用法如下:
- jcmd -l :列出当前所有运行的 java 进程
- jcmd pid help :列出当前运行的 java 进程可以执行的操作(command)
- jcmd pid|main-class PerfCounter.print :打印性能相关信息
- jcmd pid|main-class -f filename :读取文件中的命令并执行,#开头的行会被当作注视忽略
- jcmd pid|main-class command [arguments] arguments可以通过jcmd pid help command查看
支持的参数如下:
命令 |
描述 |
VM.uptime |
查看JVM的启动时长 |
GC.class_histogram |
查看JVM的类信息,可以查看每个类的实例数量和占用空间大小 |
Thread.print |
查看JVM的Thread Dump |
GC.heap_dump filename |
生成JVM的Heap Dump,指定生成的文件名 |
VM.system_properties |
查看JVM的属性信息 |
VM.flags |
查看JVM的启动参数,可以查看-X和-XX参数 |
VM.command_line |
查看JVM的启动命令行 |
GC.run_finalization |
对JVM执行 |
GC.run |
对JVM执行java.lang.System.gc(),提醒垃圾收集器进行垃圾收集,但具体JVM有没有进行垃圾收集却无法确定。 |
PerfCounter.print |
查看JVM性能信息 |
VM.native_memory |
JVM的native memory大小 |
ManagementAgent.stop |
停止Management Agent |
ManagementAgent.start |
启动Management Agent |
ManagementAgent.start_local |
启动本地Management Agent |
VM.classloader_stats |
打印Classloader详细信息 |
GC.rotate_log |
GC日志 |
GC.class_stats |
加载的类的详细信息 |
GC.finalizer_info |
GC调用finalize方法的信息 |
GC.heap_info |
GC堆的相关信息 |
VM.dynlibs |
动态加载的jar包 |
VM.version |
VM版本信息 |
本人最常用的是PerfCounter.print、GC.class_histogram、Thread.print和VM.flags,效果如下:
PerfCounter.print查看JVM性能相关信息:
jcmd 1755 PerfCounter.print
1755: java.ci.totalTime=13601090874 java.cls.loadedClasses=14492 java.cls.sharedLoadedClasses=0 java.cls.sharedUnloadedClasses=0 java.cls.unloadedClasses=0 java.property.java.class.path="/opt/elasticsearch-6.3.0/lib/elasticsearch-6.3.0.jar:/opt/elasticsearch-6.3.0/lib/elasticsearch-x-content-6.3.0.jar:/opt/elasticsearch-6.3.0/lib/elasticsearch-cli-6.3.0.jar:/opt/elasticsearch-6.3.0/lib/elasticsearch-core-6.3.0.jar:/opt/elasticsearch-6.3.0/lib/lucene-core-7.3.1.jar:/opt/elasticsearch-6.3.0/lib/lucene-analyzers-common-7.3.1.jar:/opt/elasticsearch-6.3.0/lib/lucene-backward-codecs-7.3.1.jar:/opt/elasticsearch-6.3.0/lib/lucene-grouping-7.3.1.jar:/opt/elasticsearch-6.3.0/lib/lucene-highlighter-7.3.1.jar:/opt/elasticsearch-6.3.0/lib/lucene-join-7.3.1.jar:/opt/elasticsearch-6.3.0/lib/lucene-memory-7.3.1.jar:/opt/elasticsearch-6.3.0/lib/lucene-misc-7.3.1.jar:/opt/elasticsearch-6.3.0/lib/lucene-queries-7.3.1.jar:/opt/elasticsearch-6.3.0/lib/lucene-queryparser-7.3.1.jar:/opt/elasticsearch-6.3.0/lib/lucene-sandbox-7.3.1.jar:/opt/elasticsearch-6.3.0/lib/lucene-spatial-7.3.1.jar:/opt/elasticsearch-6.3.0/lib/lucene-spatial-extras-7.3.1.jar:/opt/elasticsearch-6.3.0/lib/lucene-spatial3d-7.3.1.jar:/opt/elastic" java.property.java.endorsed.dirs="/opt/jdk1.8.0_191/jre/lib/endorsed" java.property.java.ext.dirs="/opt/jdk1.8.0_191/jre/lib/ext:/usr/java/packages/lib/ext" java.property.java.home="/opt/jdk1.8.0_191/jre" java.property.java.library.path="/usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib" java.property.java.version="1.8.0_191" java.property.java.vm.info="mixed mode"
查看GC情况:
jcmd 1755 GC.class_histogram
1755: num #instances #bytes class name ---------------------------------------------- 1: 5432 18997040 [B 2: 132477 11619136 [C 3: 152697 4886304 java.util.HashMap$Node 4: 122068 2929632 java.lang.String 5: 43778 2101344 java.util.HashMap 6: 19537 1977768 [Ljava.util.HashMap$Node; 7: 15145 1660888 java.lang.Class 8: 49096 1571072 java.util.concurrent.ConcurrentHashMap$Node 9: 17505 1177936 [Ljava.lang.Object; 10: 34698 1110336 java.util.Collections$UnmodifiableMap 11: 40684 976416 org.elasticsearch.painless.Definition$MethodKey 12: 7135 627880 java.lang.reflect.Method 13: 6878 623656 [I 14: 9786 548016 org.elasticsearch.painless.Definition$Struct 15: 30215 483440 java.lang.Object 16: 5851 468080 java.lang.reflect.Constructor 17: 8012 448672 java.lang.invoke.MemberName 18: 154 365248 [Ljava.util.concurrent.ConcurrentHashMap$Node; 19: 15518 356192 [Ljava.lang.Class;
查看thread dump:
jcmd 1755 Thread.print
1755: 2021-01-11 23:05:26 Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.191-b12 mixed mode): "elasticsearch[fantuan-tech-node-1][flush][T#1]" #43 daemon prio=5 os_prio=0 tid=0x00007f366c02a800 nid=0x743 waiting on condition [0x00007f36442e6000] java.lang.Thread.State: WAITING (parking) at sun.misc.Unsafe.park(Native Method) - parking to wait for <0x00000000c66614a8> (a org.elasticsearch.common.util.concurrent.EsExecutors$ExecutorScalingQueue) at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175) at java.util.concurrent.LinkedTransferQueue.awaitMatch(LinkedTransferQueue.java:737) at java.util.concurrent.LinkedTransferQueue.xfer(LinkedTransferQueue.java:647) at java.util.concurrent.LinkedTransferQueue.take(LinkedTransferQueue.java:1269) at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:748)
查看VM.flags:
jcmd 1755 VM.flags
1755: -XX:+AlwaysPreTouch -XX:CICompilerCount=2 -XX:CMSInitiatingOccupancyFraction=75 -XX:ErrorFile=logs/hs_err_pid%p.log -XX:GCLogFileSize=67108864 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=data -XX:InitialHeapSize=1073741824 -XX:MaxHeapSize=1073741824 -XX:MaxNewSize=87228416 -XX:MaxTenuringThreshold=6 -XX:MinHeapDeltaBytes=196608 -XX:NewSize=87228416 -XX:NumberOfGCLogFiles=32 -XX:OldPLABSize=16 -XX:OldSize=986513408 -XX:-OmitStackTraceInFastThrow -XX:+PrintGC -XX:+PrintGCApplicationStoppedTime -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintTenuringDistribution -XX:ThreadStackSize=1024 -XX:+UseCMSInitiatingOccupancyOnly -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseConcMarkSweepGC -XX:+UseFastUnorderedTimeStamps -XX:+UseGCLogFileRotation -XX:+UseParNewGC
二、jmap
jmap用于打印一个进程、可执行core文件、远程debug服务的堆内存信息,用于堆内存相关的排查,用法如下:
- jmap [ options ] pid
- jmap [ options ] executable core
- jmap [ options ] [ pid ] server-id@ remote-hostname-or-IP
当进程运行于一个64位的虚拟机的话,需要使用jmap -J-d64 -heap pid,参数如下:
- pid Java进程ID
- executable 生成核心转储的java可执行文件
- core 核心文件
- remote-hostname-or-IP 远程debug服务器的名称或者IP
- server-id 唯一ID,假如一台主机上多个远程debug服务,用于区分
options参数有如下可选项:
- 无可选项 默认打印共享对象映射信息。
- -dump:[live,] format=b,file=filename 打印Java堆内存信息,生成名字为filename,格式为hprof的文件,live参数是可选的,如果指定了则只dump出acitve objects。
- -finalizerinfo 打印关于等待结束的对象的信息。
- -heap 打印heap的概要信息,GC使用的算法,heap的配置及wise heap的使用情况.
- -histo[:live] 打印每个class的实例数目,内存占用,类全名信息. VM的内部类名字开头会加上前缀”*”. 如果live子参数加上后,只统计活的对象数量
- -clstats 打印classloader,父classloader以及所加载的类的数量以及大小。
- -F 当使用jmap -dump或者jamp -histo打印无响应的时候使用-F强制打印。不支持live可选项。
- -h 打印帮助信息
- -help 打印帮助信息
- -Jflag 传递标志给Java虚拟机。
三、jstack
jstack用于打印某个进程、核心文件或者远程debug服务器的线程栈信息,在排查多线程问题时非常方便。
- jstack [ options ] pid
- jstack [ options ] executable core
- jstack [ options ] [ server-id@ ] remote-hostname-or-IP
参数说明如下:
- pid 进程ID
- executable 产生core dump的java可执行文件
- core 打印出的core文件
- remote-hostname-or-IP 远程debug服务器的名称或者IP
- server-id 唯一ID,假如一台主机上多个远程debug服务,用于区分
Options参数可选项如下:
- -F 当使用jstack -l pid没有响应的时候,使用-F强制打印栈信息。
- -l 打印关于锁的额外的信息。
- -m 打印具有Java和本机C/C++帧的混合模式的堆栈信息,请注意-m无法用于remote debug server
- -h 打印帮助信息
- -help 打印帮助信息
四、jstat
jstat用于打印JVM的统计信息,可以显示出虚拟机进程中的类加载信息,内存和垃圾收集,JIT编译等信息,在排查JVM垃圾收集相关问题时非常有用,也是使用频率很高的一个工具,用法如下
jstat [ generalOption | outputOptions vmid [interval [s|ms] ] [count] ]
- generalOption 输入的参数可选项,使用-help或者-options可查询相关可选项
- outputOptions 输出的参数可选项
- vmid 进程ID
- interval [s|ms] 间隔的个时间
- count 打印的次数,缺省的时候是打印无数次
generalOption的常见选项如下:
1、-class : 打印classloader的行为和统计信息
$ jstat -class 14998 Loaded Bytes Unloaded Bytes Time 54958 116718.7 464 633.7 183.61
- Loaded 加载class的数量
- Bytes class字节大小
- Unloaded 未加载class的数量
- Bytes 未加载class的字节大小
- Time 加载花费的时间
2、-compiler:Hotspot JIT编译器行为和统计信息
$ jstat -compiler 14998 Compiled Failed Invalid Time FailedType FailedMethod 36902 5 0 253.24 1 com/intellij/codeInspection/bytecodeAnalysis/ConstractAnalysis ProcessState
- Compiled 编译数量
- Failed 编译失败数量
- Invalid 非法的类数量
- Time 编译耗时
- FailedType 失败类型
- FailedMethod 失败方法的全限定名
3、-gc: 垃圾回收器的行为和统计信息
$ jstat -gc 14998
输出参数的一些说明如下:
- S0C survivor0区的总容量
- S1C survivor1去的总容量
- S0U survivor0区已使用的容量
- S1U survivor1区已使用的容量
- EC Eden区的总容量
- EU Eden区已使用的容量
- OC Old区的总容量
- OU Old区已使用的容量
- PC 当前perm区的容量(KB)
- PU 当前perm区已使用的容量(KB)
- YGC 新生代垃圾回收次数
- YGCT 新生代垃圾回收时间
- FGC 老年代垃圾回收次数
- FGCT 老年代垃圾回收时间
- GCT 垃圾回收总消耗时间
4、-gccapacity:与-gc类似,但是会输出Java堆各区域的容量信息
$ jstat -gccapacity 14998
- NGCMN 新生代占用的最小的空间
- NGCMX 新生到占用的最大的空间
- OGCMN 老年代占用的最小空间
- OGCMX 老年代占用的最大的空间
- OGC 当前老年代的容量(KB)
- OC 当前老年代的空间(KB)
- PGCMN perm占用的最小空间
- PGCMX perm占用的最大空间
5、-gcutil:垃圾回收概述信息
$ jstat -gcutil 14998 S0 S1 E O M CCS YGC YGCT FGC FGCT GCT 0.00 0.00 9.67 43.77 94.08 90.88 183 5.836 27 4.589 10.425
- survivor0区当前使用比例
- survivor1区当前使用比例
- Eden区当前使用比例
- Old区当前使用比例
- Metaspace区当前使用比例
- CCS压缩使用的比例
- YGC 年轻代垃圾回收次数
- FGC 老年代垃圾回收次数
- FGCT 老年代垃圾回收消耗时间
- GCT 垃圾回收消耗总时间
- -gccause 垃圾回收概述信息,与-gcutil内容一样,只是多附加了最近两次垃圾回收的原因,LGCC代表最近垃圾回收的原因,GCC代表当前垃圾回收的原因。
6、-gcnew:新生代行为和统计信息
7、-gcnewcapacity: 新生代容量统计
8、-gcold: 老年代和永久代行为和统计信息
9、-gcoldcapacity :老年代容量统计
10、-gcpermcapacity :永生代容量统计
11、-printcompilation: HotSpot编译方法统计