Chapter 3. Starting JDK Flight Recorder 3.1. Starting JDK Flight Recorder when JVM starts You can start the JDK Flight Recorder (JFR) when a Java process starts. You can modify the behavior of the JFR by adding optional parameters. Procedure Run the java command using the --XX option. USD java -XX:StartFlightRecording Demo where Demo is the name of the Java application. The JFR starts with the Java application. Example The following command starts a Java process ( Demo ) and with it initiates an hour-long flight recording which is saved to a file called demorecording.jfr : USD java -XX:StartFlightRecording=duration=1h,filename=demorecording.jfr Demo Additional resources For a detailed list of JFR options, see Java tools reference . 3.2. Starting JDK Flight Recorder on a running JVM You can use the jcmd utility to send diagnostic command requests to a running JVM. jcmd includes commands for interacting with JFR, with the most basic commands being start , dump , and stop . To interact with a JVM, jcmd requires the process id (pid) of the JVM. You can retrieve the by using the jcmd -l command which displays a list of the running JVM process ids, as well as other information such as the main class and command-line arguments that were used to launch the processes. The jcmd utility is located under USDJAVA_HOME/bin . Procedure Start a flight recording using the following command: USD jcmd <pid> JFR.start <options> For example, the following command starts a recording named demorecording , which keeps data from the last four hours, and has size limit of 400 MB: USD jcmd <pid> JFR.start name=demorecording maxage=4h maxsize=400MB Additional resources For a detailed list of jcmd options, see jcmd Tools Reference . 3.3. Starting the JDK Flight Recorder on JVM by using the JDK Mission Control application The JDK Mission Control (JMC) application has a Flight Recording Wizard that allows for a streamlined experience of starting and configuring flight recordings. Procedure Open the JVM Browser. USD JAVA_HOME/bin/jmc Right-click a JVM in JVM Browser view and select Start Flight Recording . The Flight Recording Wizard opens. Figure 3.1. JMC JFR Wizard The JDK Flight Recording Wizard has three pages: The first page of the wizard contains general settings for the flight recording including: Name of the recording Path and filename to which the recording is saved Whether the recording is a fixed-time or continuous recording, which event template will be used Description of the recording The second page contains event options for the flight recording. You can configure the level of detail that Garbage Collections, Memory Profiling, and Method Sampling and other events record. The third page contains settings for the event details. You can turn events on or off, enable the recording of stack traces, and alter the time threshold required to record an event. Edit the settings for the recording. Click Finish . The wizard exits and the flight recording starts. 3.4. Defining and using the custom event API The JDK Flight Recorder (JFR) is an event recorder that includes the custom event API. The custom event API, stored in the jdk.jfr module, is the software interface that enables your application to communicate with the JFR. The JFR API includes classes that you can use to manage recordings and create custom events for your Java application, JVM, or operating system. Before you use the custom event API to monitor an event, you must define a name and metadata for your custom event type. You can define a JFR base event, such as a Duration , Instant , Requestable , or Time event , by extending the Event class. Specifically, you can add fields, such as duration values, to the class that matches data types defined by the application payload attributes. After you define an Event class, you can create event objects. This procedure demonstrates how to use a custom event type with JFR and JDK Mission Control (JMC) to analyze the runtime performance of a simple example program. Procedure In your custom event type, in the Event class, use the @name annotation to name the custom event. This name displays in the JMC graphical user interface (GUI). Example of defining a custom event type name in the Event class @Name("SampleCustomEvent") public class SampleCustomEvent extends Event {...} Define the metadata for your Event class and its attributes, such as name, category, and labels. Labels display event types for a client, such as JMC. Note Large recording files might cause performance issues, and this might affect how you would like to interact with the files. Make sure you correctly define the number of event recording annotations you need. Defining unnecessary annotations might increase the size of your recording files. Example of defining annotations for a sample Event class @Name("SampleCustomEvent") 1 @Label("Sample Custom Event") @Category("Sample events") @Description("Custom Event to demonstrate the Custom Events API") @StackTrace(false) 2 public class SampleCustomEvent extends Event { @Label("Method") 3 public String method; @Label("Generated Number") public int number; @Label("Size") @DataAmount 4 public int size; } 1 Details annotations, such as @Name , that define metadata for how the custom event displays on the JMC GUI. 2 The @StackTrace annotation increases the size of a flight recording. By default, the JFR does not include the stackTrace of the location that was created for the event. 3 The @Label annotations define parameters for each method, such as resource methods for HTTP requests. 4 The @DataAmount annotation includes an attribute that defines the data amount in bits of bytes. JMC automatically renders the data amount in other units, such as megabytes (MB). Define contextual information in your Event class. This information sets the request handling behavior of your custom event type, so that you configure an event type to collect specific JFR data. Example of defining a simple main class and an event loop public class Main { private static int requestsSent; public static void main(String[] args) { // Register the custom event FlightRecorder.register(SampleCustomEvent.class); // Do some work to generate the events while (requestsSent <= 1000) { try { eventLoopBody(); Thread.sleep(100); } catch (Exception e) { e.printStackTrace(); } } } private static void eventLoopBody() { // Create and begin the event SampleCustomEvent event = new SampleCustomEvent(); event.begin(); // Generate some data for the event Random r = new Random(); int someData = r.nextInt(1000000); // Set the event fields event.method = "eventLoopBody"; event.number = someData; event.size = 4; // End the event event.end(); event.commit(); requestsSent++; } In the preceding example, the simple main class registers events, and the event loop populates the event fields and then emits the custom events. Examine an event type in the application of your choice, such as the JMC or the JFR tool. Figure 3.2. Example of examining an event type in JMC A JFR recording can include different event types. You can examine each event type in your application. Additional resources For more information about JMC, see Introduction to JDK Mission Control .

Commands:
@Name("SampleCustomEvent") public class SampleCustomEvent extends Event {...}
@Name("SampleCustomEvent") 1 @Label("Sample Custom Event") @Category("Sample events") @Description("Custom Event to demonstrate the Custom Events API") @StackTrace(false) 2 public class SampleCustomEvent extends Event { @Label("Method") 3 public String method; @Label("Generated Number") public int number; @Label("Size") @DataAmount 4 public int size; }
public class Main { private static int requestsSent; public static void main(String[] args) { // Register the custom event FlightRecorder.register(SampleCustomEvent.class); // Do some work to generate the events while (requestsSent <= 1000) { try { eventLoopBody(); Thread.sleep(100); } catch (Exception e) { e.printStackTrace(); } } } private static void eventLoopBody() { // Create and begin the event SampleCustomEvent event = new SampleCustomEvent(); event.begin(); // Generate some data for the event Random r = new Random(); int someData = r.nextInt(1000000); // Set the event fields event.method = "eventLoopBody"; event.number = someData; event.size = 4; // End the event event.end(); event.commit(); requestsSent++; }