[JVM] 如何通过jcmd画火焰图

2020-05-20

火焰图是我们日常的比较好用的一个性能分析工具,通过火焰图我们可以分析进程在哪些方法耗时较长,通过分析热点代码调用,找出可以优化的性能瓶颈

jcmd能做什么

在JDK 1.7的版本之后,新增了一个JVM相关的诊断工具jcmd,它可以用来进行JVM堆、线程信息的导出,进行采样分析,这里只简单的介绍它的功能,具体深入的使用方式可以查看文档

如何使用,执行jcmd -h

1
2
3
4
PerfCounter.print display the counters exposed by this process
-f read and execute commands from the file
-l list JVM processes on the local machine
-h this help

查看本机的JVM进程jcmd -l

1
2
3
4
5
6
54769 org.apache.hadoop.hdfs.server.datanode.DataNode
54870 org.apache.hadoop.hdfs.server.namenode.SecondaryNameNode
54665 org.apache.hadoop.hdfs.server.namenode.NameNode
54987 org.apache.hadoop.yarn.server.resourcemanager.ResourceManager
55325 sun.tools.jcmd.JCmd -l
55070 org.apache.hadoop.yarn.server.nodemanager.NodeManager

查看制定进程的性能统计jcmd 54665 PerfCounter.print

1
2
3
4
5
6
7
54665:
java.ci.totalTime=4754838518
java.cls.loadedClasses=4867
java.cls.sharedLoadedClasses=0
java.cls.sharedUnloadedClasses=0
java.cls.unloadedClasses=0
...

列出当前进行可以执行的操作jcmd 54665 help

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
54665:
The following commands are available:
JFR.stop
JFR.start
JFR.dump
JFR.check
VM.native_memory
VM.check_commercial_features
VM.unlock_commercial_features
ManagementAgent.stop
ManagementAgent.start_local
ManagementAgent.start
GC.rotate_log
Thread.print
GC.class_stats
GC.class_histogram
GC.heap_dump
GC.run_finalization
GC.run
VM.uptime
VM.flags
VM.system_properties
VM.command_line
VM.version
help

查看对应的命令怎么使用jcmd 54665 help VM.unlock_commercial_features

1
2
3
4
5
6
7
8
9
54665:
VM.unlock_commercial_features
Unlock commercial features

Impact: Low: No impact

Permission: java.lang.management.ManagementPermission(control)

Syntax: VM.unlock_commercial_features

对线程进行dump操作jcmd 54665 Thread.print

1
2
3
4
5
6
7
8
9
10
11
54665:
2020-06-03 20:45:23
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.131-b11 mixed mode):

"Attach Listener" #49 daemon prio=9 os_prio=31 tid=0x00007f9b5673b000 nid=0xa50b waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE

"CacheReplicationMonitor(1004132509)" #48 prio=5 os_prio=31 tid=0x00007f9b58b7d800 nid=0x8d03 waiting on condition [0x000070000a0de000]
java.lang.Thread.State: TIMED_WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
...

如何通过jcmd画火焰图

通过上面的简单的jcmd的介绍,我们已经可以简单的使用jcmd了,那么我们如何通过jcmd工具去生成我们想要分析进程的火焰图呢?

第一步解锁jdk的商业特性

1
jcmd pid VM.unlock_commercial_features

启动JFR(Java Flight Recorder),收集300s的JVM信息,得到output.jfr文件

1
jcmd pid JFR.start name=test duration=300s settings=profile.jfc filename=output.jfr

下载FlameGraph项目

1
git clone https://github.com/brendangregg/FlameGraph.git

下载jfr-flame-graph项目进行构建

1
git clone https://github.com/chrishantha/jfr-flame-graph.git

生成火焰图

1
2
3
export FLAMEGRAPH_DIR=~/FlameGraph
cd ~/jfr-flame-graph/build/install/jfr-flame-graph/bin
./create_flamegraph.sh -f ~/output.jfr -i > ~/flamegraph.svg

然后用浏览器打开,就可以点击对应的调用栈了

除此之外,其实也有软件Java Mission Control可以直接打开output.jfr文件,例如

点击代码,调用树,进行对应的分析

参考文章

  1. JVM性能调优工具之jcmd
  2. GC日志分析网站:gceasy.io