使用JCMD采集JFR
我在上一篇博客中简单介绍了JCMD的几个常见的用法,可以进行线程dump,内存转存,内存对象直方图分析等。可以说,JCMD集成了以前我们常用的jstack,jps,jmap等命令,就像瑞士军刀一样,all in one。除了这些功能,JCMD还能够采集JFR信息进行性能分析。
JFR: Java Fly Record
JFR全称java fly record,是Java平台性能分析和事件采集的框架,且是JDK自带的工具。JFR可以采集到low-level的性能信息,而且对Java程序的性能影响几乎可以忽略不计,主要是因为JFR是直接采集的JVM内部的信息。如果你要将JFR商用,那么你需要去买oracle的商业证书,当然开发环境可以免费使用。
解锁Java程序的商业特性
由于JFR是商用的,所以需要解锁Java程序的商业feature,通过如下的JVM参数:
java -XX:+UnlockCommercialFeatures -XX:+FlightRecorder
在JDK 1.8u40之后版本,不需要在启动的时候通过flag来解锁了,可以动态的解锁。
首先用jcmd查看下商业feature是否已解锁:
➜ target git:(master) ✗ jcmd 12174 VM.check_commercial_features
12174:
Commercial Features are locked.
如果没有解锁,使用下面的命令解锁:
➜ target git:(master) ✗ jcmd 12174 VM.unlock_commercial_features
12174:
Commercial Features now unlocked.
这时候,就可以运行许JFR采集任务了。
采集JFR
采集JFR有两种方式:
- 固定时长的采集
- 持续不断的采集
对于固定时长的采集,JFR会采集固定时长的事件并转存到指定的文件。对于持续不断的采集,不会把采集的事件转存到文件,需要手动去转存。JFR会把采集到的事件存到一个全局缓存,当缓存满了,会丢弃缓存中老的事件。所以,当你手动转存时,只会转存缓存中可用的数据,
启用持续不断的缓存,在发现问题的时候可以很方便的转存采集到的事件。
在我们启动JFR采集任务时,可以指定一个配置文件,配置文件定义了采集哪些事件,以及阈值。
JDK默认自带了两个配置文件,
➜ Home ll jre/lib/jfr
total 80
-rw-rw-r-- 1 root wheel 20K 7 22 2017 default.jfc
-rw-rw-r-- 1 root wheel 20K 7 22 2017 profile.jfc
在运行"连续不断"的JFR采集任务时,使用默认配置default.jfc
。默认配置的开销很低,适用于一直运行,这样不会影响Java程序的性能。
profile.jfc
采集的事件力度更细。
采集固定时长的JFR
下面的命令启动了一个10分钟的JFR任务:
jcmd 12174 JFR.start name=10min.jfr settings=profile delay=3s duration=5m filename=/Users/jianyuan/Personal/10_min.jfr compress=true
12174:
Recording 2 scheduled to start in 3 s. The result will be written to:
/Users/jianyuan/Personal/10_min.jfr
可以使用JFR.check
来查看当前有哪些JFR任务在执行:
➜ jcmd 12174 JFR.check
12174:
Recording: recording=2 name="10min.jfr" duration=5m filename="/Users/jianyuan/Personal/10_min.jfr" compress=true (running)
持续采集JFR
通过下面命令启动一个持续不断的JFR任务:
➜ jcmd 12174 JFR.start name=endless settings=profile delay=3s duration=0 compress=true
12174:
Recording 3 scheduled to start in 3 s. No limit (duration/maxsize/maxage) in use.
Use JFR.dump name=endless filename=FILEPATH to copy recording data to file.
之前提过,对于这种持续采集的任务,我们需要手动转存:
➜ jcmd 12174 JFR.dump recording=3 filename="/Users/jianyuan/Personal/dump_endless.jfr" compress=true
12174:
Dumped recording 3, 646.0 kB (before compresssion) written to:
/Users/jianyuan/Personal/dump_endless.jfr
当然,我们可以手动停止正在运行的JFR任务:
➜ jcmd 12174 JFR.stop recording=3
12174:
Stopped recording 3.
分析JFR文件
JDK为我们提供了一个分析JFR的工具,叫JMC (Java Mission Control)。如果你Java的环境变量正确配置了,直接在命令行运行jmc
就可以打开JMC程序。打开之前dump的一个jfr文件:
JMC根据内存,线程等分了多个Tab,根据你要定位的具体问题浏览不同的Tab。
文章同步发布在我的个人博客上,欢迎拍砖。
传送门: 使用JCMD采集JFR