Java Flight Recorder

  java

Order

This article mainly studies the use of Java Flight Recorder.

Command

There are mainly five commands, configure, check, start, dump, stop. In order of execution, first start, then dump, and finally stop.

JFR.configure

Parameter describe Value type Default value
globalbuffercount Specify the number of global buffers. modifymemorysizeThe parameter affects this value. Long Default value dependencymemorysizeParameters.
globalbuffersize Specifies the global buffers size in bytes.memorysizeParameters affect global buffers. Long Default value dependencymemorysizeParameters.
maxchunksize Specifies the maximum value of a single data chunk in bytes. Long 12582912
memorysize Specifies the total memory size in bytes Long 10485760
repositorypath Specifies the storage path for recordings before it is written to a persisted file String The default is the system temporary directory, Oracle Solaris and Linux are/tmp. windows system, takeTMPEnvironmental variable value
stackdepth Specifies Stack depth for stack traces Long 64
thread_buffer_size Specify the Local buffer size in bytes for each thread. modifying this parameter is not recommended and may reduce performance. Long 8192
threadbufferstodisk Is thread buffers allowed to write directly to disk when buffer thread is blocked? Boolean false
samplethreads Do you want to turn on thread sampling? Boolean true

Command instance

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

Parameter describe Value type Default value
delay Specify how long to delay before recording starts Integer type plus s indicates seconds.mIndicates minutes, orhIndicates hours 0s
disk Whether to write data to disk when recording Boolean true
dumponexit Whether to write records to disk when JVM is shut down. if true but not specifiedfilename, the file name is system generated and contains process ID, recording ID, and currenttimesstamp (for example,hotspot-pid-47496-id-1-2018_01_25_19_10_41.jfr), the file path is the process startup path. Boolean false
duration Specify duration of recording Integer type plus s indicates seconds.mIndicates minutes, orhIndicates hours 0s (forever)
filename Specifies the file path to record data when stopping, or uses the process usage directory if not specified, for examplerecording.jfr`/home/user/recordings/recording.jfr`c:\recordings\recording.jfr String No default value
maxage Specifies the maximum survival time of the recorded data on the disk, which is valid only when the disk parameter is true. Integer type plus s indicates seconds.mIndicates minutes, orhIndicates hours 0s (forever)
maxsize Specifies the maximum size of the recorded data on the disk, the default unit bytes, and specifiesmOrMIt means a trillion.gOrGIndicates g, valid only if the disk parameter is true, which cannot be compared tomaxchunksizeThe parameter value is small. Long 0 (no maximum size)
name Specify the file name of the record, or generate by default if not specified. String The default is system generated.
path-to-gc-roots Introduced by JDK 10, specifies the path of GC Roots to be collected before the end of recording. This parameter is helpful for checking memory leaks, but collection is time consuming and only enabled when and only when memory leaks are suspected. IfsettingsThe parameter is set toprofileThen the collected information includes stack trace of potential memory leak objects. Boolean false
settings Specifies the profile of the record, if notJRE_HOME/lib/jfrIn the directory, specify the full path. If you want to specify more than one path, separate them with commas. The default paths aredefault.jfc: This configuration has low overhead and can be used for continuous operation.profile.jfc: more data is provided than default, but the cost is higher, which affects the performance and is suitable for collecting information in a short time. String JRE_HOME/lib/jfr/default.jfc

Command instance

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

Parameter describe Value type Default value
name Specify file name String No default value
verbose Print event settings Boolean false

Command instance

jcmd 5793 JFR.check
5793:
Recording 1: name=demojfr maxsize=250.0MB (running)

JFR.dump

Parameter describe Value type Default value
filename(required) Specify the path to dump write, or if not, use the directory where the process started, for example:recording.jfr`/home/user/recordings/recording.jfr`c:\recordings\recording.jfr String No default value
name(required) Specify records to dump String No default value
path-to-gc-roots Introduced by JDK 10, specifies the path of GC Roots to be collected before the end of recording. This parameter is helpful for checking memory leaks, but collection is time consuming and only enabled when and only when memory leaks are suspected. Boolean false

Command instance

jcmd 5793 JFR.dump name=demojfr filename=/tmp/demo.jfr
5793:
Dumped recording "demojfr", 480.8 kB written to:

/tmp/demo.jfr

JFR.stop

Parameter describe Value type Default value
filename Specifies the path to write data when stopping. If not specified, it defaults to the directory where the process starts, for examplerecording.jfr`/home/user/recordings/recording.jfr`c:\recordings\recording.jfr String No default value
name Specifies the name of the record to stop String No default value

Command instance

jcmd 5793 JFR.stop name=demojfr
5793:
Stopped recording "demojfr".

JMC

The screenshot of JMC opening jfr file instance is as follows:
图片描述

Read JFR file

    @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());
    }
  • Directly using jdk’s api can parse jfr files and read RecordedEvent
  • The eventType type output is as follows:
[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]

In addition to the system-defined eventType, you can also customize the eventevent.

Custom 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;
    }
}
  • Publish event
        DemoEvent event = new DemoEvent();
        event.setMessage("hello, world!");
        event.commit();

After parsing the jfr file using the api, you can see a custom event whose name is com.example.jfr.DemoEvent
You can start-xx with the following parameters: startlightrecording = duration = 120s, filename =/tmp/event.jfr, settings = default, name = demoventrecording

Related modules

JDK11 has two modules on jfr, jdk.jfr.jmod and jdk.management.jfr.jmod, which are as follows:

➜  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

Summary

  • Java Flight Recorder is an excellent diagnostic tool for Java applications. It used to be a commercial feature and is now open source in java11. jfr fi les it exports can be analyzed with Java Mission Control.
  • JDK11 has built-in API, which can be used to parse jfr files or publish custom events in applications.
  • JFR can be started by JVM command, or it can be operated at runtime by using JFR. of jcmd, which is very convenient.

doc