skip to content

Java Flight Recorder (JFR)

Java Flight Recorder is built into the JVM and records allocation, GC, lock, exception and sampling events at roughly one percent overhead, analyzed in JDK Mission Control. It is the standard answer to how do you profile a live production JVM.

part ofJavaoverview, primer and where to startread it →
on this pageshow

questions

5

How do you start a JFR recording — both at JVM launch and on an already-running process — and how do you produce a .jfr file from it?

level: middleimportance: must knowfreq 60%

answer

  1. Launch flag: -XX:StartFlightRecording=duration,filename,settings
  2. Live process: jcmd <pid> JFR.start / .check / .dump / .stop
  3. dump = snapshot while running; stop = end recording
  4. settings=default (cheap) vs profile (richer)
  5. Programmatic: jdk.jfr.Recording

basics

~20 s

At launch, add the JVM flag -XX:StartFlightRecording with options like duration and filename. On a running process, use the jcmd tool: 'jcmd <pid> JFR.start', then 'JFR.dump' to write a .jfr file and 'JFR.stop' to end it.

solid answer

~40 s

There are two main ways to drive JFR. At JVM startup you pass -XX:StartFlightRecording=... with comma-separated options, e.g. -XX:StartFlightRecording=duration=60s,filename=app.jfr,settings=profile. For a process already running, you use the jcmd command-line tool against its PID: jcmd <pid> JFR.start name=rec settings=profile to begin, jcmd <pid> JFR.dump name=rec filename=app.jfr to write the buffered data to a file, jcmd <pid> JFR.check to list active recordings, and jcmd <pid> JFR.stop name=rec to end it. The settings parameter selects a configuration template — typically 'default' (very low overhead, safe for continuous production use) or 'profile' (richer events, slightly higher cost, for focused investigation). You can also dump on exit (dumponexit=true) or automatically on OutOfMemoryError. The output .jfr file is then opened in JDK Mission Control.

code

java · 21 lines
java
// Start at launch (shell):
//   java -XX:StartFlightRecording=duration=60s,filename=app.jfr,settings=profile -jar app.jar
//
// Control a running process by PID (shell):
//   jcmd <pid> JFR.start name=rec settings=default maxage=10m maxsize=100m
//   jcmd <pid> JFR.check
//   jcmd <pid> JFR.dump  name=rec filename=incident.jfr
//   jcmd <pid> JFR.stop  name=rec

// Or programmatically, inside the application, via the jdk.jfr API:
import jdk.jfr.Recording;
import java.nio.file.Path;
import java.time.Duration;

var recording = new Recording();
recording.setDuration(Duration.ofSeconds(60));
recording.setName("rec");
recording.start();
// ... let the app run ...
recording.dump(Path.of("app.jfr")); // write buffered events to a file
recording.stop();

go deeper

for a junior

Knows the two ways to start: the -XX:StartFlightRecording launch flag and jcmd on a live process, and that the result is a .jfr file.

for a middle

Can list the common options (duration, filename, settings, name, maxage/maxsize), distinguish dump vs stop, and pick default vs profile appropriately.

for a senior

Designs an always-on continuous recording with a bounded ring buffer (maxage/maxsize) plus incident-triggered JFR.dump, and knows the programmatic jdk.jfr API and dumponexit / dump-on-OOM triggers.

for a principal

Standardizes JFR enablement across the fleet (custom .jfc templates, FlightRecorderOptions tuning, repository placement), automates dump collection, and balances event coverage against overhead budgets.

## The two entry points JFR is controlled either **at JVM launch** (a flag) or **on a live JVM** (the `jcmd` tool). Both produce the same thing: a binary **`.jfr`** recording file. ### 1. At launch — `-XX:StartFlightRecording` You add a single JVM flag with comma-separated `key=value` options: ``` java -XX:StartFlightRecording=duration=60s,filename=app.jfr,settings=profile -jar app.jar ``` Common options: - **`duration`** — how long to record (omit it for an *unbounded/continuous* recording). - **`filename`** — where to write the `.jfr` (if omitted, you must dump it later). - **`settings`** — the configuration template name (`default` or `profile`, or a custom `.jfc` file). - **`name`** — a label so you can refer to this recording later via `jcmd`. - **`maxsize` / `maxage`** — cap the buffered data by size or by time window (for continuous recordings). - **`dumponexit=true`** — write the file automatically when the JVM shuts down. ### 2. On a running process — `jcmd` `jcmd` is a JDK diagnostic command tool. You target a process by its **PID** (process id; `jcmd` with no arguments or `jps` lists Java PIDs). The JFR sub-commands: ``` jcmd <pid> JFR.start name=rec settings=profile jcmd <pid> JFR.check # list active recordings jcmd <pid> JFR.dump name=rec filename=app.jfr # snapshot current buffer to a file jcmd <pid> JFR.stop name=rec filename=app.jfr # stop AND write the file ``` Key distinction: **`JFR.dump`** writes out what is buffered *so far* while the recording keeps going; **`JFR.stop`** ends the recording (and can also write the file). This is the basis of the 'always-on, dump-on-incident' pattern: start an unbounded recording with a `maxage`/`maxsize` ring buffer, and when something goes wrong, `JFR.dump` the recent window. ### Settings templates: default vs profile The **`settings`** parameter chooses how much to record: - **`default`** — conservative, **< 1% overhead**, intended to be safe for continuous production recording. - **`profile`** — denser sampling and more event types, **slightly higher overhead**, for a focused profiling session. - A **custom `.jfc`** file (you can author one in JMC) lets you turn individual event types and their thresholds on or off. ### Other triggers - **`-XX:FlightRecorderOptions`** tunes global buffer sizes and repository location. - You can also start/stop recordings **programmatically** via the `jdk.jfr` API (`Recording` class) inside the application. ### Where the file goes next The `.jfr` is a self-contained binary file of typed events; you open it in **JDK Mission Control (JMC)** (or parse it with the `jdk.jfr.consumer` API / `jfr print` CLI) to analyze.

  • What is the difference between JFR.dump and JFR.stop?
    JFR.dump writes the currently buffered events to a file while the recording continues running; JFR.stop ends the recording entirely (and can also write the file). dump is what you use for the 'always-on, snapshot on incident' pattern.
  • When would you choose the 'default' settings template over 'profile'?
    Use 'default' for continuous, always-on recording in production because it keeps overhead under ~1%. Use 'profile' for a time-boxed investigation where you want denser method sampling and more event types and can tolerate slightly higher cost.

saying these in an interview costs you the question

  • Thinking you need a third-party tool to start a recording — it is a JVM flag or jcmd, both shipped with the JDK.
  • Confusing JFR.dump (snapshot, keeps recording) with JFR.stop (ends recording).
  • Believing you must restart the JVM with a flag to profile — jcmd attaches to an already-running process.
  • Saying 'profile' settings are always best — they cost more; 'default' is the production-safe template.

context

open as a page

What is Java Flight Recorder (JFR), and what makes it suitable for use in production rather than only in a test environment?

level: juniorimportance: should knowfreq 55%

basics

~20 s

JFR is a profiling and event-recording tool built into the JVM. It records what your application does (allocations, GC, locks, exceptions, method samples) with very low overhead—around 1% or less—so you can safely leave it on in production.

open as a page

Once you have a .jfr file, how do you analyze it, and what is JDK Mission Control's role? How might custom application events fit in?

level: middleimportance: should knowfreq 40%

basics

~20 s

You open the .jfr file in JDK Mission Control (JMC), a desktop app that shows automated analysis and views like CPU usage, allocations, GC, locks, and exceptions. You can also read .jfr files from the command line with 'jfr print' or programmatically with the jdk.jfr.consumer API, and define your own custom events for app-specific telemetry.

open as a page

What is the difference between a continuous (always-on) JFR recording and a profiling recording, and how does this shape an incident-investigation strategy in production?

level: seniorimportance: should knowfreq 42%

basics

~20 s

A continuous recording runs all the time with low-overhead settings and a bounded ring buffer, so you can dump the recent history when something goes wrong. A profiling recording is a short, time-boxed session with richer events and slightly higher cost, used for a focused investigation.

open as a page

Describe JFR's event model: what kinds of events does it capture, and how does the sampling-and-buffering design keep the cost low enough for production?

level: seniorimportance: should knowfreq 48%

basics

~20 s

JFR records typed 'events' for things like object allocation, garbage collection, lock contention, thrown exceptions, file/socket I/O, and periodic method (CPU) samples. Events go into per-thread buffers and CPU profiling uses sampling, so the overhead stays around 1%.

open as a page