JFR 实战之一
自从2016年左右开始干SRE, 就了解到 JFR 是一个非常有用的工具, 尤其在性能调优这一块. 在好几本书和一些文章中都有人提及过, 但是很少见有人用它来解决实际的问题. 可能的原因包括: JFR的很多事件都是JVM本身暴露的稍底层的一些时间, 不熟悉JVM运行机制的话, 很难从这边比较容易的看出问题. JFR 如果用在生产环境是需要付费的.
为了从理论到实践, 这里就在本地开发环境打开JFR, 然后收集一些数据, 然后解读.
设置环境, 开启JFR
本地正好有个 Java 应用: Pycharm, 通过下面的命令可以看到它的一些启动参数:
$ jcmd
60759 jdk.jcmd/sun.tools.jcmd.JCmd
22348 com.intellij.idea.Main
$ jcmd 22348 VM.command_line
$ jcmd 22348 VM.flags -all | grep FlightRecorder
bool FlightRecorder = false {product} {default}
ccstr FlightRecorderOptions = {product} {default}
我们修改 Pycharm 的 JVM 参数. 从 Pycharm 菜单依次点击: Help -> Edit Custom VM Options. 就打开了 ~/Library/Application\ Support/JetBrains/PyCharmCE2023.3/pycharm.vmoptions
. 添加下面选项:
-XX:+UnlockCommercialFeatures
-XX:+FlightRecorder
上面的修改类似于 java -XX:+UnlockCommercialFeatures -XX:+FlightRecorder MyApp
重启 Pycharm, 我们再次检查它的参数:
jcmd 62236 VM.flags -all | grep FlightRecorder
bool FlightRecorder = true {product} {command line}
ccstr FlightRecorderOptions = {product} {default}
收集数据
上面的-XX:+FlightRecorder
选项只是说明我们打开了 JFR 的开关, 真正的收集事件并未开始. 通常我们可以通过 jcmd
命令行或者一些GUI工具(JConsole, Java Mission Control等)来开始收集.
通过运行 jcmd
命令, 我们可以看到有关 JFR 的一些命令, 然后通过 help
能看到对应子命令的更多内容:
$ jcmd <pid> help | grep JFR
JFR.check
JFR.configure
JFR.dump
JFR.start
JFR.stop
$ jcmd 62236 help JFR.start
... 可以看到很多参数省略 ...
通过如下的命令, 我们可以启动收集:
$ jcmd 62236 JFR.start name=sample1,filename=/tmp/sample1.jfr,during=1m
62236:
Started recording 1. No limit specified, using maxsize=250MB as default.
Use jcmd 62236 JFR.dump name=sample1,filename=/tmp/sample1.jfr,during=1m filename=FILEPATH to copy recording data to file.
查看这个收集任务 并把数据保存到文件
$ jcmd 62236 JFR.check
62236:
Recording 1: name=sample1,filename=/tmp/sample1.jfr,during=1m maxsize=250.0MB (running)
jcmd 62236 JFR.dump name=sample1,filename=/tmp/sample1.jfr,during=1m filename=/tmp/sample1.jfr
62236:
Dumped recording "sample1,filename=/tmp/sample1.jfr,during=1m", 6.2 MB written to:
/private/tmp/sample1.jfr
关于这几个子命令的更多信息: https://docs.oracle.com/javacomponents/jmc-5-4/jfr-runtime-guide/comline.htm#JFRUH188
解读数据
解读数据需要 Java Mission Control (JMC), 下载页面: https://www.oracle.com/java/technologies/javase/products-jmc8-downloads.html
启动 JMC, 然后打开刚才的文件.
事件类型
JFR 收集3类数据类型:
- 持续事件: 需要一段时间才会发生,并在完成时记录。你可以设置持续事件的阈值,以便只记录持续时间超过指定时间段的事件。
- 瞬时事件: 立即发生,并立即记录。
- 样本事件: 以固定间隔记录,以提供系统活动的样本。你可以配置采样发生的频率。
你是最棒的SRE