Java Flight Recording (JFR)

The following article is provided on an advice basis only. This article references third party software that may require licensing.

JFR is a profiling and event collection framework built into the Oracle JDK. It allows Java administrators and developers to gather detailed low-level information about how the Java Virtual Machine (JVM) and the Java application are behaving. JFR has an almost unnoticeable impact on the performance of a Java application running in the JVM (overhead is usually well below 1%).

You may be asked to provide a JFR recording by Push Technology support. This article explains how to make a JFR recording.

It is important that your recording captures the issue happening. A JFR recorded while the server is behaving normally is rarely useful.

Creating a Recording

Two startup flags must be enabled on the JVM for which you want to do flight recording.

-XX:+UnlockCommercialFeatures
-XX:+FlightRecorder

Configuring the Diffusion server to automatically record a JFR on startup

This can be done by editing the startup script diffusion.sh or diffusion.bat and adding the following line:

ENABLE_JFR=" -XX:+UnlockCommercialFeatures -XX:+UnlockDiagnosticVMOptions -XX:+DebugNonSafepoints -XX:+FlightRecorder -XX:FlightRecorderOptions=defaultrecording=true,dumponexit=true,dumponexitpath=../logs -XX:StartFlightRecording=compress=true,maxsize=512m"

For this configuration the only requirement is to replace the value of dumponexitpath with the path you want your JFR files to be saved to. You can set the recording to have a maximum size or age with the following parameters:

maxsize=size

Append the letter k or K to indicate kilobytes, m or M to indicate megabytes, g or G to indicate gigabytes, or do not specify any suffix to set the size in bytes.

maxage=age

Append the letter s to indicate seconds, m to indicate minutes, h to indicate hours, or d to indicate days. You can also configure the recording to be written to a file when the JVM exits by setting the dumponexit parameter to true and specifying a path to save it to, like this:

-XX:FlightRecorderOptions=defaultrecording=true,dumponexit=true,dumponexitpath=../logs

The JFR recordings will be found under the logs folder in your Diffusion installation. The full example given above will configure the Diffusion startup script to record a JFR recording when Diffusion is started and write it to a file in the logs directory designated by dumponexitpath when it exits. In this example, the recording is set to keep the latest 512m which should be sufficient data. When starting Diffusion you will see a confirmation of the recording in the console output:

Started recording 1.

Use JFR.dump recording=1 filename=FILEPATH to copy recording data to file.

Creating a dump of the recording from the command line.

In order to manually create a dump of the current recording, issue these commands in the following order: The jps command is used to get the PID for the Diffusion server, in this case 24054.

$ jps

24054 Diffusion
24265 Jps

Then jcmd JFR.check can be issued to get an overview of all current recordings:

$ jcmd 24054 JFR.check

24054:
Recording: recording=1 name="Recording 1" (running)

‘Recording 1’ is currently running, so you can write a dump of its state with the following command:

$ jcmd 24054 JFR.dump recording=1 filename=~/TestRecording.jfr

24054:
Dumped recording 1, 2.7 MB written to:

~/TestRecording.jfr

You can then open the JFR file that was created in Java Mission Control to analyse the dump that was taken.

Using the Command Line to start a manual recording.

In order to start a manual recording, you need the PID for the Diffusion process, which you can obtain as in the previous example. In this case, the PID is 12093:

$ jps

12093 Diffusion
12141 Jps

To begin a 60 second recording, issue the following command using the PID obtained above:

$ jcmd 12093 JFR.start duration=60s sfilename=testrecording.jfr

Starting the recording from the command line has its advantages as it can be scripted or run on servers where GUI access is impractical.

Using the Java Mission Control GUI tool to start a manual recording.

Start Java Mission Control by entering the following command into the command line:

$ jmc

Click the ‘Start Using’ button at the bottom of the window. Run the application that you would like to profile. The application will show in the list in the left panel. Right click on the program and select ‘Start Flight Recording’. In the dialog, choose the name, length, and location of the recording and press Next.

Java Flight Recording (JFR)_image_1

In the next screen you can configure the settings and then press Finish. This saves the recording to the specified location. We recommend that you take thread dumps every 60s.

Java Flight Recording (JFR)_image_2

Saving a JFR recording prior to exit

Diffusion out-of-the-box is configured to use dumponexit=true which will save a JFR when the JVM exits deliberately or otherwise. This can be useful when diagnosing unplanned outages, however it is known to truncate the coverage of the resulting JFR. To save all collected JFR data before a planned outage use JFR.dump and JFR.stop to save and cease JFR data recording.

Sending to Support

Once your recording has been created, please compress the JFR file and send to Push Technology Support. If the file is too large to be emailed, please contact our support team, who will make alternative arrangements.

Recommended optimisation

We propose that the following change is made to the profile configuration (typically found at $JAVA_HOME/jre/lib/jfr/profile.jfc) due to a performance issue in the JVM:

    <event path="java/socket_read">
<setting name="enabled">false</setting>
<setting name="stackTrace">true</setting>
<setting name="threshold" control="http://www.oracle.com/hotspot/jvm/socket-io-threshold">10 ms</setting>
</event>

<event path="java/socket_write">
<setting name="enabled">false</setting>
<setting name="stackTrace">true</setting>
<setting name="threshold" control="http://www.oracle.com/hotspot/jvm/socket-io-threshold">10 ms</setting>
</event>

You can find more details about this issue which has now been resolved at this page of the JDK bug system.