Java Flight Recorder小试牛刀

本文主要研究一下Java Flight Recorder的使用。

命令

主要有5个命令,configure、check、start、dump、stop。执行顺序的话,先start再dump,最后stop。

JFR.configure

参数描述值类型默认值
globalbuffercount指定global buffers的数量. 修改 memorysize参数会影响该值.Long默认值依赖 memorysize 参数.
globalbuffersize指定global buffers大小, 单位bytes. 修改 memorysize 参数会影响到global buffers.Long默认值依赖 memorysize 参数.
maxchunksize指定单个data chunk的最大值, 单位bytesLong12582912
memorysize指定总内存大小, 单位bytesLong10485760
repositorypath指定recordings在写入到持久化文件之前的存储路径String默认为系统临时目录,Oracle Solaris以及Linux是/tmp.windows系统的话,取TMP环境变量值
stackdepth指定stack traces的Stack depthLong64
thread_buffer_size指定每个thread的Local buffer size, 单位bytes. 不建议修改此参数,可能会降低性能Long8192
threadbufferstodisk是否允许thread buffers在buffer thread阻塞的时候直接写到磁盘Booleanfalse
samplethreads是否开启thread samplingBooleantrue
命令实例
jcmd 5793 JFR.configure
5793:
Current configuration:

Repository path: /private/var/folders/9r/v55wkcr91m5_g8h7lhgjzgr00000gn/T/2018_09_27_16_30_53_5793

Stack depth: 64
Global buffer count: 20
Global buffer size: 512.0 kB
Thread buffer size: 8.0 kB
Memory size: 10.0 MB
Max chunk size: 12.0 MB
Sample threads: true

JFR.start

参数描述值类型默认值
delay指定延时多长时间才开始记录Integer类型加s表示秒, m表示分钟, 或者h表示小时0s
disk记录的时候是否写数据到磁盘Booleantrue
dumponexit是否在JVM关闭时写记录到磁盘. 如果为true但没有指定filename, 则文件名为系统生成,包含process ID, recording ID,以及 current time stamp (例如,hotspot-pid-47496-id-1-2018_01_25_19_10_41.jfr),文件路径为进程启动路径 .Booleanfalse
duration指定记录时长Integer类型加s表示秒, m表示分钟, 或者h表示小时0s (forever)
filename指定停止时记录数据的文件路径,如果未指定,则使用进程使用目录,例如recording.jfr`/home/user/recordings/recording.jfr`c:\recordings\recording.jfr StringNo default value
maxage指定记录数据在磁盘的最大存活时间,当disk参数为true时才有效Integer类型加s表示秒, m表示分钟, 或者h表示小时0s (forever)
maxsize指定记录数据在磁盘的最大大小,默认单位bytes,指定mM表示兆,gG表示G,只有当disk参数为true时才有效,该值不能比maxchunksize参数值小.Long0 (no maximum size)
name指定记录文件名,如未指定则默认生成.String默认为系统生成.
path-to-gc-rootsJDK 10引入的,指定在记录结束前要收集的GC Roots的路径.该参数有助于排查内存泄露,但是收集比较耗时,当且仅当怀疑有内存泄露时才启用。如果settings参数设置为profile, 则收集的信息包括潜在内存泄露对象的stack trace.Booleanfalse
settings指定记录的配置文件,如果不是JRE_HOME/lib/jfr目录下的要指定全路径,要指定多个的话,用逗号分隔。默认路径有default.jfc: 该配置开销低,可以用于持续运行.profile.jfc: 则提供比default更多的数据,但是开销大一些,对性能有所影响,适合短时间收集信息用StringJRE_HOME/lib/jfr/default.jfc
命令实例
jcmd 5793 JFR.start name=demojfr dumponexit=true
5793:
Started recording 1. No limit specified, using maxsize=250MB as default.

Use jcmd 5793 JFR.dump name=demojfr filename=FILEPATH to copy recording data to file.

JFR.check

参数描述值类型默认值
name指定文件名StringNo default value
verbose是否打印event settingsBooleanfalse
命令实例
jcmd 5793 JFR.check
5793:
Recording 1: name=demojfr maxsize=250.0MB (running)

JFR.dump

参数描述值类型默认值
filename(required)指定dump写入的路径,如果未指定,则使用进程启动的目录,例如:recording.jfr`/home/user/recordings/recording.jfr`c:\recordings\recording.jfr StringNo default value
name(required)指定要dump的记录StringNo default value
path-to-gc-rootsJDK 10引入的,指定在记录结束前要收集的GC Roots的路径.该参数有助于排查内存泄露,但是收集比较耗时,当且仅当怀疑有内存泄露时才启用.Booleanfalse
命令实例
jcmd 5793 JFR.dump name=demojfr filename=/tmp/demo.jfr
5793:
Dumped recording "demojfr", 480.8 kB written to:

/tmp/demo.jfr

JFR.stop

参数描述值类型默认值
filename指定停止时数据写入的路径.如果没有指定则默认为进程启动的目录,例如recording.jfr`/home/user/recordings/recording.jfr`c:\recordings\recording.jfr StringNo default value
name指定要stop的记录的名称StringNo default value
命令实例
jcmd 5793 JFR.stop name=demojfr
5793:
Stopped recording "demojfr".

JMC

JMC打开jfr文件实例截图如下:
图片描述

读取JFR文件

    @Test
    public void testReadJfr() throws IOException {
        Path p = Paths.get(getClass().getClassLoader().getResource("demo.jfr").getPath());
        List<RecordedEvent> events = RecordingFile.readAllEvents(p);
        events.stream()
                .forEach(e -> LOGGER.info("eventType:{},startTime:{},endTime:{},fields:{}",e.getEventType().getName(),e.getStartTime(),e.getEndTime(),e.getFields()));
        List<String> eventNames = events.stream()
                .map(e -> e.getEventType().getName())
                .distinct()
                .collect(Collectors.toList());
        System.out.println(eventNames.toString());
    }
  • 直接使用jdk的api即可以解析jfr文件,读出RecordedEvent
  • eventType类型输出如下:
[jdk.ExceptionStatistics, jdk.NativeMethodSample, jdk.ThreadSleep, jdk.JavaMonitorWait, jdk.CPULoad, jdk.JavaThreadStatistics, jdk.ClassLoadingStatistics, jdk.CompilerStatistics, jdk.ClassLoaderStatistics, jdk.ModuleExport, jdk.CodeCacheStatistics, jdk.CodeSweeperStatistics, jdk.GCConfiguration, jdk.ActiveSetting, jdk.ActiveRecording, jdk.InitialSystemProperty, jdk.InitialEnvironmentVariable, jdk.CPUInformation, jdk.CPUTimeStampCounter, jdk.ThreadAllocationStatistics, jdk.PhysicalMemory, jdk.NativeLibrary, jdk.CompilerConfiguration, jdk.CodeCacheConfiguration, jdk.CodeSweeperConfiguration, jdk.IntFlag, jdk.UnsignedIntFlag, jdk.LongFlag, jdk.UnsignedLongFlag, jdk.DoubleFlag, jdk.BooleanFlag, jdk.StringFlag, jdk.ThreadEnd, jdk.ThreadCPULoad, jdk.NetworkUtilization, jdk.ThreadStart, jdk.ThreadContextSwitchRate, jdk.GCSurvivorConfiguration, jdk.GCTLABConfiguration, jdk.GCHeapConfiguration, jdk.YoungGenerationConfiguration, jdk.SystemProcess, jdk.ThreadDump, jdk.JVMInformation, jdk.OSInformation, jdk.ModuleRequire]
除了系统定义的eventType,还可以自定义event

自定义event

  • DemoEvent
@Label("Demo Event")
@Description("Helps the programmer getting started")
public class DemoEvent extends Event {
    @Label("Message")
    private String message;

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}
  • 发布事件
        DemoEvent event = new DemoEvent();
        event.setMessage("hello, world!");
        event.commit();
之后使用api解析jfr文件,可以看到自定义的event,其name为com.example.jfr.DemoEvent
可以使用如下参数启动-XX:StartFlightRecording=duration=120s,filename=/tmp/event.jfr,settings=default,name=DemoEventRecording

相关模块

JDK11关于jfr的模块有两个,分别是jdk.jfr.jmod以及jdk.management.jfr.jmod,其具体内容如下:

➜  jmods ../bin/jmod describe jdk.jfr.jmod
jdk.jfr@11
exports jdk.jfr
exports jdk.jfr.consumer
requires java.base mandated
qualified exports jdk.jfr.internal.management to jdk.management.jfr
contains jdk.jfr.events
contains jdk.jfr.internal
contains jdk.jfr.internal.cmd
contains jdk.jfr.internal.consumer
contains jdk.jfr.internal.dcmd
contains jdk.jfr.internal.handlers
contains jdk.jfr.internal.instrument
contains jdk.jfr.internal.jfc
contains jdk.jfr.internal.settings
contains jdk.jfr.internal.test
contains jdk.jfr.internal.types
platform macos-amd64

➜  jmods ../bin/jmod describe jdk.management.jfr.jmod
jdk.management.jfr@11
exports jdk.management.jfr
requires java.base mandated
requires java.management transitive
requires jdk.jfr
requires jdk.management
provides sun.management.spi.PlatformMBeanProvider with jdk.management.jfr.internal.FlightRecorderMXBeanProvider
contains jdk.management.jfr.internal
platform macos-amd64

小结

  • Java Flight Recorder是一款优秀的java应用诊断工具,以前是商业版的特性,现在在java11当中开源出来,它导出的jfr文件可以用Java Mission Control来分析。
  • JDK11内置了相关API,可以用来解析jfr文件,也可以在应用程序自定义事件发布出来
  • JFR可以采用JVM命令启动,也可以使用jcmd的JFR.开头的命令在运行时操作,非常方便

doc

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值