微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

转储 Java 飞行记录的一部分

如何解决转储 Java 飞行记录的一部分

假设我已经使用以下标志为我的 JVM 配置了连续飞行记录

java
-XX:StartFlightRecording=disk=false,dumponexit=true
-XX:FlightRecorderOptions=memorysize=200m
-jar
....

据我所知,此配置最多可在内存中存储 200mb 热点事件,达到限制时丢弃最旧的。

要转储记录,我通过 JFR.dump 使用 jcmd 命令。还有一种通过任务控制提取记录的替代方法,但由于其中存在错误,我未能成功提取在任务控制的 JVM 之外运行的记录。令人惊讶的是,MBean 服务器管理工​​作正常。

无论如何,我看到可以通过任务控制通过“转储”功能指定从连续记录转储的间隔范围,例如从 2021-01-01 13:00:00 到 2021-01-01 14 :00:00。假设当前时间是 2021-01-02 17:00:00。如何通过 JFR.dump 指定相同的间隔?查看 JFR.dump 参考,没有任何标志可以做到这一点。那么任务控制是如何做到的?

注意:我使用的是 JMC 8 和 Oracle JDK 11 0 10u8。

解决方法

不幸的是,您拥有的链接在搜索引擎中排名靠前,但它已经使用了 6 年。您可以找到最新的文档 here (JDK 16),它与 ​​JDK 11 非常相似。

无法转储基于内存的记录的一部分。在您的示例中,您必须删除 'disk=false' 和 -XX:FlightRecorderOptions,并将 'maxsize=200M' 添加到 -XX:StartFlightRecording:

$ java -XX:StartFlightRecording:maxsize=200M -jar ...

然后你可以这样做:

$ jcmd <pid> JFR.dump begin=2021-01-01T13:00:00 end=2021-01-01T14:00:00

日期时间格式为 ISO-8601,这是 LocalDataTime.toString() 和 Instant.toString() 产生的。

如果您省略结束时间,JFR.dump 将假定它应该在您执行转储时结束,如果您指定相对时间,它将相对于转储时间。

例如,转储最后一小时:

$ jcmd <pid> JFR.dump begin=-1h

也可以使用maxage参数来限制数据,例如:

$ jcmd <pid> JFR.dump maxage=1h

maxsize 参数可用于指定要包含多少数据,例如:

$ jcmd <pid> JFR.dump maxsize=50MB

另一种选择是创建两个基于磁盘的记录:

$ java -XX:StartFlightRecording:maxsize=200M,name=sized
       -XX:StartFlightRecording:maxage=1h,name=aged 
       -jar ...

$ jcmd <pid> JFR.dump name=aged 

两次录音的开销与一次相同。

(我不会太在意基于磁盘的记录的开销。JFR 中的所有数据都是无锁写入并由后台线程刷新。磁盘和内存之间的开销差异通常无法衡量)

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。