29.1 Java Flight Recorder

Capture low-overhead performance and diagnostic data for production applications using built-in JFR events.

Starting a Recording

java -XX:StartFlightRecording=settings=profile,filename=recording.jfr,duration=60s MyApp

Settings:

  • default: Low overhead (~1%).
  • profile: More detail (~2% overhead).

Recording at Runtime (JFR API)

import jdk.jfr.Recording;
import jdk.jfr.Configuration;
import java.nio.file.Path;

Configuration config = Configuration.getConfiguration("profile");
try (Recording rec = new Recording(config)) {
  rec.start();
  // application logic
  Thread.sleep(10_000);
  rec.dump(Path.of("runtime.jfr"));
}

Key Event Types

  • jdk.Compilation: JIT compilation activity.
  • jdk.GarbageCollection: GC pause times.
  • jdk.ObjectAllocationSample: Allocation hotspots.
  • jdk.JavaMonitorEnter: Lock contention.
  • jdk.ThreadPark: Thread parking events.
  • jdk.FileRead/FileWrite: I/O operations.

Analyzing with JDK Mission Control (JMC)

jmc recording.jfr

Visualize timelines, identify bottlenecks (GC, locks, allocations), and drill into hot methods.

Custom Events

import jdk.jfr.*;

@Name("com.example.MyEvent")
@Label("My Custom Event")
class MyEvent extends Event {
  @Label("Operation Name") String operation;
  @Label("Duration") long durationMs;
}

MyEvent evt = new MyEvent();
evt.begin();
// business logic
evt.end();
evt.operation = "processOrder";
evt.durationMs = evt.getDuration().toMillis();
if (evt.shouldCommit()) evt.commit();

Production Use

  • Run with settings=default for continuous monitoring.
  • Store recordings externally for post-mortem analysis.
  • Use JFR with monitoring tools (Prometheus, Grafana via JMX).

Guidance

  • Start with profile settings for troubleshooting; use default in production.
  • Combine JFR with GC logs and JMX metrics for comprehensive observability.
  • Analyze allocation profiles to identify memory churn.
  • Use custom events to track business-critical operations.