序本文主要研究一下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的最大值, 单位bytesLong12582912memorysize指定总内存大小, 单位bytesLong10485760repositorypath指定recordings在写入到持久化文件之前的存储路径String默认为系统临时目录,Oracle Solaris以及Linux是/tmp.windows系统的话,取TMP环境变量值stackdepth指定stack traces的Stack depthLong64thread_buffer_size指定每个thread的Local buffer size, 单位bytes. 不建议修改此参数,可能会降低性能Long8192threadbufferstodisk是否允许thread buffers在buffer thread阻塞的时候直接写到磁盘Booleanfalsesamplethreads是否开启thread samplingBooleantrue命令实例jcmd 5793 JFR.configure5793:Current configuration:Repository path: /private/var/folders/9r/v55wkcr91m5_g8h7lhgjzgr00000gn/T/2018_09_27_16_30_53_5793Stack depth: 64Global buffer count: 20Global buffer size: 512.0 kBThread buffer size: 8.0 kBMemory size: 10.0 MBMax chunk size: 12.0 MBSample threads: trueJFR.start参数描述值类型默认值delay指定延时多长时间才开始记录Integer类型加s表示秒, m表示分钟, 或者h表示小时0sdisk记录的时候是否写数据到磁盘Booleantruedumponexit是否在JVM关闭时写记录到磁盘. 如果为true但没有指定filename, 则文件名为系统生成,包含process ID, recording ID,以及 current time stamp (例如,hotspot-pid-47496-id-1-2018_01_25_19_10_41.jfr),文件路径为进程启动路径 .Booleanfalseduration指定记录时长Integer类型加s表示秒, m表示分钟, 或者h表示小时0s (forever)filename指定停止时记录数据的文件路径,如果未指定,则使用进程使用目录,例如recording.jfr/home/user/recordings/recording.jfr
c:\recordings\recording.jfrStringNo default valuemaxage指定记录数据在磁盘的最大存活时间,当disk参数为true时才有效Integer类型加s表示秒, m表示分钟, 或者h表示小时0s (forever)maxsize指定记录数据在磁盘的最大大小,默认单位bytes,指定m或M表示兆,g或G表示G,只有当disk参数为true时才有效,该值不能比maxchunksize参数值小.Long0 (no maximum size)name指定记录文件名,如未指定则默认生成.String默认为系统生成.path-to-gc-rootsJDK 10引入的,指定在记录结束前要收集的GC Roots的路径.该参数有助于排查内存泄露,但是收集比较耗时,当且仅当怀疑有内存泄露时才启用。如果settings参数设置为profile, 则收集的信息包括潜在内存泄露对象的stack trace.Booleanfalsesettings指定记录的配置文件,如果不是JRE_HOME/lib/jfr目录下的要指定全路径,要指定多个的话,用逗号分隔。默认路径有default.jfc: 该配置开销低,可以用于持续运行.profile.jfc: 则提供比default更多的数据,但是开销大一些,对性能有所影响,适合短时间收集信息用StringJRE_HOME/lib/jfr/default.jfc命令实例jcmd 5793 JFR.start name=demojfr dumponexit=true5793: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 valueverbose是否打印event settingsBooleanfalse命令实例jcmd 5793 JFR.check5793:Recording 1: name=demojfr maxsize=250.0MB (running)JFR.dump参数描述值类型默认值filename(required)指定dump写入的路径,如果未指定,则使用进程启动的目录,例如:recording.jfr/home/user/recordings/recording.jfr
c:\recordings\recording.jfrStringNo default valuename(required)指定要dump的记录StringNo default valuepath-to-gc-rootsJDK 10引入的,指定在记录结束前要收集的GC Roots的路径.该参数有助于排查内存泄露,但是收集比较耗时,当且仅当怀疑有内存泄露时才启用.Booleanfalse命令实例jcmd 5793 JFR.dump name=demojfr filename=/tmp/demo.jfr5793:Dumped recording “demojfr”, 480.8 kB written to:/tmp/demo.jfrJFR.stop参数描述值类型默认值filename指定停止时数据写入的路径.如果没有指定则默认为进程启动的目录,例如recording.jfr/home/user/recordings/recording.jfr
c:\recordings\recording.jfrStringNo default valuename指定要stop的记录的名称StringNo default value命令实例jcmd 5793 JFR.stop name=demojfr5793:Stopped recording “demojfr”.JMCJMC打开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文件,读出RecordedEventeventType类型输出如下:[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自定义eventDemoEvent@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.jmodjdk.jfr@11exports jdk.jfrexports jdk.jfr.consumerrequires java.base mandatedqualified exports jdk.jfr.internal.management to jdk.management.jfrcontains jdk.jfr.eventscontains jdk.jfr.internalcontains jdk.jfr.internal.cmdcontains jdk.jfr.internal.consumercontains jdk.jfr.internal.dcmdcontains jdk.jfr.internal.handlerscontains jdk.jfr.internal.instrumentcontains jdk.jfr.internal.jfccontains jdk.jfr.internal.settingscontains jdk.jfr.internal.testcontains jdk.jfr.internal.typesplatform macos-amd64➜ jmods ../bin/jmod describe jdk.management.jfr.jmodjdk.management.jfr@11exports jdk.management.jfrrequires java.base mandatedrequires java.management transitiverequires jdk.jfrrequires jdk.managementprovides sun.management.spi.PlatformMBeanProvider with jdk.management.jfr.internal.FlightRecorderMXBeanProvidercontains jdk.management.jfr.internalplatform macos-amd64小结Java Flight Recorder是一款优秀的java应用诊断工具,以前是商业版的特性,现在在java11当中开源出来,它导出的jfr文件可以用Java Mission Control来分析。JDK11内置了相关API,可以用来解析jfr文件,也可以在应用程序自定义事件发布出来JFR可以采用JVM命令启动,也可以使用jcmd的JFR.开头的命令在运行时操作,非常方便docUsing Java Flight RecorderJava Flight Recorder Cheat Sheet2 Diagnostic Command ReferenceClarifying some confusion around Java Flight RecordingsJava Flight Recorder:The Secret Arrow in Your Quiver