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).

New ebook 🔥

Learn 84 ways to solve common data engineering problems with cloud services.

👉 I want my Early Access edition

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:

/tmp/app_flight_recording.jfr

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
6491 sun.tools.jcmd.JCmd
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
6455:

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

Started recording 2. The result will be written to:

/tmp/app_flight_recording_from_jcmd.jfr

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.