Java Flight Recorder

Versions: Java 8

Java Mission Control (JMC) described in previous post comes with another tool helping to understand what happens in the JVM. This tool is the Java Flight Recorder (JFR).

Looking for a better data engineering position and skills?

You have been working as a data engineer but feel stuck? You don't have any new challenges and are still writing the same jobs all over again? You have now different options. You can try to look for a new job, now or later, or learn from the others! "Become a Better Data Engineer" initiative is one of these places where you can find online learning resources where the theory meets the practice. They will help you prepare maybe for the next job, or at least, improve your current skillset without looking for something else.

👉 I'm interested in improving my data engineering skillset

See you there, Bartosz

The goal of this post is to show some simple uses of Java Flight Recorder. The first part presents it in a global image. The next section is about the configuration and the 3 different options of use. The last part shows how these 3 options can be used in the context of really running application.

Java Flight Recorder definition

A very clear metaphor for the Java Flight Recorder is the one of airplane's black box. This flight recorder accumulates the events observed during the fly. The role of JFR is the same. It accumulates events produced by the JVM on runtime.

According to the Oracle Java guide, the performance impact on the application is less than 2%. This small impact can be explained by the fact that accumulated data is stored in off-heap buffers. The fresh metrics are sent to thread-local off-heap buffers. Once these buffers are fullfilled, the accumulated data is moved to the global buffers. When these buffers are fullfilled in their turn, the data is finally flushed to disk. The disk flush can be disabled. With this configuration the JFR behaves as a circular buffer.

Circular buffer

A data structure known also as: circular queue, cyclic buffer or ring buffer. It uses a single and fixed-size buffer. When the buffer is full, each new added elements overrides the oldest element in the buffer.

The information collected by the JFR is called event. An event has: name, timestamp and optional payload having data describing what happened (e.g. heap size before and after the event). Among registered events we can distinguish for instance: threads waiting for locks, GC activity, CPU usage, I/O, servlet requests metrics or JDBC stats. More globally, the JFR records 3 types of events, all occurring at specific point of time:

Java Flight Recorder configuration

The events are recorded only if -XX:+UnlockCommercialFeatures -XX:+FlightRecorder are specified. The JFR can be used in one of 3 manners:

How the registered data can be read ? As you can already deduce, the simplest and the most readable manner uses JMC UI. Dumped files can be read directly from File > Open File... part. It gives exactly the same output as the screens attached to the point about JMC in above list.

Java Flight Recorder example

To test the JFR we'll use the same code as for the Java Missiong Control example. The use of JFR from JMC UI is straightforward. As told in the previous section, we must right click on the observed application and select the option "Start Flight Recording". 2 configuration windows can appear if "Next" button is clicked instead of "Finish":

The recording is physically started after the clicking on "Finish" button.

The configuration is much simpler in the case of command line options defined at application's start. In our case we'll use the following flags: -XX:+UnlockCommercialFeatures -XX:+FlightRecorder -XX:StartFlightRecording=duration=1d,filename=/tmp/app_flight_recording.dump. After starting the application, the logging indicating successful registering should be shown:

Started recording 1. The result will be written to:


After the application stop, all events registered within 1 day are saved to /tmp/app_flight_recording.jfr file. And they can be simply read from JMC.

Similar configuration is used when starting the JFR from jcmd tool. The first step consists on finding the PID of profiled application by executing the jcmd command. It prints the list of all executed processes:

bartosz:/tmp$ jcmd
6455 com.intellij.rt.execution.application.AppMain com.waitingforcode.App
3086 com.intellij.idea.Main

Our monitored application has the PID of 6455. The recording can be started with the following command:

bartosz:/tmp$ jcmd 6455 JFR.start duration=1d filename=/tmp/app_flight_recording_from_jcmd.jfr

It gives the same output as in the case of command line:

Started recording 2. The result will be written to:


Both dump files registered with command line and jcmd can be opened from JMC. It gives the results shown in the following screens:

This post described the use of Java Flight Recorded in JVM-based applications monitoring. The JFR looks very much like airplane's black box that captures all events during the fly. JFR behaves equally because it records everything that happens on runtime. This "everything" can of course be configured, exactly as other properties such as: recording duration, dump file. The JFR can be started in 3 different manners: from JMC UI, from command line and with the help of jcmd tool. All of them allow to read the recorded events from the JMC UI.