You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何通过JFR.dump命令指定时间区间导出JVM持续Flight Record?JMC实现该功能的原理是什么?

如何通过JFR.dump实现指定时间区间的Flight Record导出?

首先得跟你确认:你说的完全没错,JFR.dump命令本身确实没有直接支持指定时间区间导出的参数,但我们可以通过结合JDK自带的工具链,实现和JMC一样的时间区间筛选效果。下面分两部分给你拆解:

一、用jcmd+JFR命令行工具实现时间区间导出

你的JVM是配置了内存型持续录制(disk=false),内存缓冲区上限200MB,满了就覆盖最早的事件。要导出指定时间段的记录,可以按这两步来:

  1. 先导出内存中的完整录制到临时文件
    先用JFR.dump把当前内存里所有还没被覆盖的事件导出到一个临时JFR文件:

    jcmd <你的JVM进程ID> JFR.dump filename=/tmp/full_temp.jfr
    
  2. jfr extract裁剪指定时间区间
    Oracle JDK 11自带了jfr命令(在$JAVA_HOME/bin目录下),它支持对已生成的JFR文件做时间过滤。你可以用extract子命令精准提取目标时间段的内容:

    jfr extract --start "2021-01-01 13:00:00" --end "2021-01-01 14:00:00" /tmp/full_temp.jfr /tmp/filtered_result.jfr
    

    要是时间格式报错,换成ISO 8601格式(比如2021-01-01T13:00:00)肯定没问题。

    注意:这个方法的前提是,你要导出的时间区间内的事件还没被内存缓冲区覆盖——毕竟你的配置是满了就丢最早的,要是目标时间段的事件已经被清掉了,那肯定提取不到。

二、JMC实现时间区间导出的底层逻辑

JMC能直接选时间区间导出,核心是利用了JFR内存缓冲区的随机访问特性

  • JFR在内存中存储事件时,会给每个事件打上精确的时间戳,并且按时间顺序组织数据结构。
  • JMC通过MBean连接到目标JVM后,并不会先导出所有事件,而是直接向JFR的底层组件发送请求,只拉取指定时间范围内的事件数据,然后直接打包成JFR文件下载到本地。
  • 这种方式比先导出全量再过滤高效很多,可惜你遇到了JMC的bug没法用这个功能,不过上面的工具组合方案可以达到同样的效果。

另外给你个小建议:如果经常需要导出历史时间区间的记录,建议把持续录制改成磁盘持久化模式(disk=true),加上maxsizemaxage参数,让JFR自动把事件存到磁盘,并且保留指定时长/大小的记录。比如:

java -XX:StartFlightRecording=disk=true,dumponexit=true,maxsize=10g,maxage=7d -XX:FlightRecorderOptions=memorysize=200m -jar 你的应用.jar

这样之后用jfr extract可以直接从磁盘文件里提取指定区间,不用再担心内存缓冲区覆盖旧事件的问题。


内容的提问来源于stack exchange,提问作者Dragas

火山引擎 最新活动