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?
answer
- JMC = standalone desktop app, separate download, automated analysis + drill-downs
- Drill-downs: method profiling/flame graph, allocation, GC, locks, exceptions, I/O
- CLI: jfr print / jfr summary; programmatic: jdk.jfr.consumer
- Custom events: extend jdk.jfr.Event, begin()/commit(), @Threshold
- Correlate custom + JVM events on one timeline
basics
~20 sYou 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.
solid answer
~50 sA .jfr file is a self-contained binary stream of typed events. The primary tool to analyze it is **JDK Mission Control (JMC)** — a separate desktop application (not bundled in the JDK) that opens recordings and presents both an **automated analysis** (rules that flag likely problems: GC pressure, lock contention, high allocation, blocked threads) and drill-down pages for method profiling (flame graphs/hot methods), memory/allocation, GC pauses, threads, locks, exceptions, and I/O. For lightweight or scripted inspection you can use the **`jfr`** command-line tool (`jfr print`, `jfr summary`) shipped with the JDK, or consume events programmatically with the **`jdk.jfr.consumer`** API to build custom reports or pipe events elsewhere. Beyond the built-in events, applications can define **custom JFR events** by extending `jdk.jfr.Event`, annotating fields, and committing them — so domain-level telemetry (e.g. 'order processed', with latency and order-id fields) sits in the same recording and timeline as JVM events, enabling correlation.
code
java · 25 linesimport jdk.jfr.*;
@Name("com.example.OrderProcessed")
@Label("Order Processed")
@Category({"Application", "Orders"})
@Threshold("10 ms") // only record orders that took >10ms
class OrderProcessedEvent extends Event {
@Label("Order Id") String orderId;
@Label("Item Count") int itemCount;
}
void process(Order order) {
var event = new OrderProcessedEvent();
event.begin(); // start timing
event.orderId = order.id();
event.itemCount = order.items().size();
// ... do the work ...
event.commit(); // record into the JFR stream (subject to @Threshold)
}
// Analyze later:
// GUI: open the .jfr in JDK Mission Control (JMC)
// CLI: jfr print --events com.example.OrderProcessed app.jfr
// summary: jfr summary app.jfr
// programmatic: jdk.jfr.consumer.RecordingFile / EventStreamgo deeper
Knows you open a .jfr in JDK Mission Control (JMC) to see CPU, memory, GC and lock views, and that JMC is a separate tool from JFR.
Can describe JMC's automated analysis and drill-down pages, the jfr CLI (print/summary), and that applications can define custom events by extending jdk.jfr.Event.
Uses correlation across event types (including custom events) to localize root causes, scripts analysis with the jfr tool or jdk.jfr.consumer API, and leverages JFR event streaming for live consumption.
Builds an analysis pipeline around JFR — automated .jfr ingestion/rules, standardized custom application events as first-class telemetry, and dashboards fed by the consumer/streaming API across services.
## The .jfr file A recording is a **binary file of typed events** — self-describing (it embeds its event-type metadata), so any compatible tool can read it without prior knowledge of the schema. ## JDK Mission Control (JMC) **JMC** is the flagship analysis tool. Key facts: - It is a **standalone desktop application**, downloaded **separately** from the JDK (it is not the `java` runtime; it is a GUI app). - It opens a `.jfr` and runs an **automated analysis**: a set of rules scores the recording and surfaces likely issues — e.g. 'significant time in GC', 'lock contention on object X', 'high allocation rate', 'threads blocked on I/O'. This gives you a prioritized starting point instead of a raw event dump. - It provides **drill-down pages**, each a view over particular event types: - **Method profiling** — aggregates execution-sample events into hot-method lists and **flame graphs** (where CPU time goes). - **Memory/Allocation** — allocation by class/thread/stack, revealing allocation pressure. - **Garbage Collection** — pause durations, frequency, before/after heap. - **Lock Instances / Threads** — contention and thread states over time. - **Exceptions, File/Socket I/O, JVM internals** — and more. - Because every event is timestamped, you can **correlate** across pages: line up a latency spike with a GC pause and an allocation burst to find a root cause. ## Command-line and programmatic analysis You do not always need a GUI: - The **`jfr`** tool (ships with the JDK) gives `jfr print file.jfr` (dump events as text, filterable by event type) and `jfr summary file.jfr` (per-event-type counts) — handy in scripts, CI, or on a headless server. - The **`jdk.jfr.consumer`** API (`RecordingFile`, `EventStream`) lets you read events in Java code to build custom reports, feed dashboards, or stream events live (since JDK 14, JFR event streaming lets you consume events as they are produced, not just from a finished file). ## Custom application events JFR is extensible: your application can define its **own event types** so business-level telemetry lives alongside JVM events in the same recording. You extend **`jdk.jfr.Event`**, add typed fields, optionally annotate with `@Name`, `@Label`, `@Category`, `@Threshold` (to filter short events), and surround the timed work with `begin()` / `commit()` (or just `commit()` for instant events). Because these custom events share the JFR timeline, you can correlate, say, an 'OrderProcessed' event's latency with the GC and lock events happening at that instant — a powerful, low-overhead alternative to scattering logging around. ## Putting it together Workflow: **dump or finish a .jfr → open in JMC for automated analysis and drill-down (or `jfr print` / a consumer for scripted use) → correlate event types (including your custom ones) to localize the root cause.** JMC turns the raw typed event stream into an actionable picture.
- How do you read a .jfr file without the JMC GUI?Use the JDK's 'jfr' command-line tool — 'jfr print file.jfr' (optionally --events to filter) or 'jfr summary file.jfr' — or read it in code with the jdk.jfr.consumer API (RecordingFile / EventStream), which also supports live event streaming since JDK 14.
- Why define a custom JFR event instead of just logging?A custom event lives on the same low-overhead JFR timeline as JVM events, so you can correlate your business operation's latency with GC pauses, lock contention, and allocations at that instant — with thresholds to drop noise — rather than parsing scattered logs.
saying these in an interview costs you the question
- Confusing JMC (the analyzer) with JFR (the recorder) — they are distinct and JMC is a separate download.
- Thinking the only way to read a .jfr is the JMC GUI — jfr print and the jdk.jfr.consumer API work headless.
- Believing custom events require a separate logging framework — JFR lets the app define its own event types in the same recording.
- Assuming JMC just shows raw events — it also runs automated rules that flag likely problems.