Server CPU usage is spiking, and response times are skyrocketing. The .jfr is recorded, but finding the cause is not a trivial task.
We reproduced a controlled CPU load and analyzed it with four tools: JMC (JDK Mission Control), VisualVM, async-profiler, and yCrash JFRPlayer. We found that all four tools identified the busy method. The analysis processes are different in each case, so we have prepared the next section to learn about the differences in research approaches and show you how to apply each method to your case.
In this article, we will compare the research approaches of these tools and show you how to use them in a particular case.
Recording vs. Profiling vs. Analysis: Understanding the Key Differences
Each tool has similar and unusual characteristics.
- Recording: Get usage data to a .jfr file with JFR
- Profiling: analysis that specializes in CPU processing, memory allocation, etc.
- Analysis: linking observed events to cause explanations
Hotspot detection is the starting point. The measurement that tells us the “location” of the phenomenon, and the analysis that determines the “cause”, make sense in the series.
JMC and VisualVM are suitable for examining existing logs; JFRPlayer has automatic diagnostics, and the async-profiler is a data collection professional specializing in JFR/Flame Graph printing.
Please note that the types of events stored in the async-profiler and standard JVM tool generation files may differ. Even in the same format, it is better to think of the content as something different.
What to Look for in a Java Flight Recorder (JFR) Analysis Tool
A useful tool should be fit for purpose for both the investigation and the people conducting it. We’ll consider the setup effort versus cost, level of automation, depth of analysis, journey to the root cause, and the most appropriate use case.
Going beyond pretty graphs, can I follow a finding back to the relevant stack or event? Can I rerun the same investigation? Could I hand it to a colleague without them having to rebuild the whole thing?
We need to distinguish between overheads caused by collection and analysis. Opening up an existing recording is not a useful metric for how much time it would take to collect – likewise, a good summary is not necessarily a measurable time saving unless we time the investigations.
Practical Example: Analyzing a Java CPU Spike with JFR
Our CpuSpikeDemo program first waits for 10 seconds, then performs a computationally intensive loop processing for about 90 seconds, and then waits for another 5 seconds. The cpu-hot-worker thread calls hotMethod(long) continuously. We have deliberately put the workload into this method to allow us to verify each tool against a known cause.
The JMC, VisualVM, and JFRPlayer tools are all exploring the same cpu-spike-02.jfr file is stored in Windows/JDK 21. In the summary view, 5,617 execution sample events were recorded for a total of 105 seconds of recording.
For async-profiler, the same application was run separately in Ubuntu under WSL2. The recording lasted approximately 24 seconds, shorter than the configured 60-second interval.
The tool versions used were JMC 9.1.2, VisualVM 2.2.1, and async-profiler 3.5. The purpose of this article is to compare the progress of the study, not the diagnostic speed or the overhead costs of collection. Memory leaks and resource conflicts are not covered by this confirmation.
Setting Up a Java CPU Spike Test
Save this app as CpuSpikeDemo.java first. After waiting for 10 seconds, the program activates the work thread for about 90 seconds and then waits for 5 seconds. Thanks to the volatile attribute, the result of the calculation remains reliably visible in all threads.
public class CpuSpikeDemo { private static volatile long result; public static void main(String[] args) throws Exception { System.out.println("PID: " + ProcessHandle.current().pid()); Thread.sleep(10_000); Thread worker = new Thread(() -> { long end = System.nanoTime() + 90_000_000_000L; while (System.nanoTime() < end) { result = hotMethod(result); } }, "cpu-hot-worker"); worker.start(); worker.join(); System.out.println("Result: " + result); Thread.sleep(5_000); } private static long hotMethod(long seed) { long value = seed; for (int i = 0; i < 1_000_000; i++) { value = value * 1664525L + 1013904223L; value ^= value >>> 13; } return value; }}
The worker thread performs CPU-intensive calculations without I/O or lock contention. This repetition naturally creates a path where the computational load is concentrated, and you can follow this path with different tools. However, this does not completely replicate the problems in the actual production environment.
Generating and Preparing JFR Recordings for Analysis
If you want to run the JVM saved tests again with JDK 21, try running this command in the source directory. However, this playback process saves the application from start to finish, so be careful not to process the original cpu-spike-02.jfr file when viewing the screenshot.
javac CpuSpikeDemo.javajava -XX:StartFlightRecording=filename=cpu-spike-repeat.jfr,settings=profile,dumponexit=true CpuSpikeDemojfr summary cpu-spike-repeat.jfr
Use the same JFR recording for JDK Mission Control (JMC), VisualVM, and yCrash JFRPlayer. Performance sampling is enabled in the configuration; however, sample counts and statistical ratios may vary between runs.
The async-profiler data comes from a separate execution of the application in WSL2. The command above reproduces the basic CPU load test, but it does not reproduce the original async-profiler recording. Refer to the official async-profiler documentation for instructions on collecting similar profiling data on supported hosts.
Comparing Four JFR Analysis Tools in Practice
With the recordings ready, how does each tool help you move from identifying a CPU hotspot to understanding its underlying cause? Let’s compare JMC, VisualVM, async-profiler, and yCrash JFRPlayer to see what each reveals, how their diagnostic workflows differ, and which approach best suits your troubleshooting needs.
1. JDK Mission Control (JMC)
JDK Mission Control is a desktop diagnostic tool for analyzing JVM runtime recordings and functional features (several versions are available for free, and installation requirements and implementation environments vary from version to version). It allows you to perform an in-depth examination of method profiling, thread states, garbage collection, and I/O operations in JFR.
Key Features
- Detailed analysis of JFR events and method profiles
- Timeline inspection of JVM activity
- Build-in automated diagnostic rules
- Headless analysis and HTML report generation via its core API
Fig: JMC’s CPU profiling view highlights the CpuSpikeDemo.hotMethod(long) hotspot and provides timeline context for investigating CPU-intensive execution.
What the Results Tell Us
The snapshot has been uploaded with the previously shared recordings. There are 5,615 samples in the cpu-hot-worker thread, and the flame graph clearly visualizes the hot method ‘CpuSpikeDemo.hotMethod(long)’. The timeline with the processor’s activity provides a chronological context to the evidence found in the call stack.
Experienced engineers can test different hypotheses with these multidimensional analyses. However, to do this, you must first understand the structure of the view, the filter criteria and what each metric means. One of the essential skills is the ability to identify where the sampling data is focused and interpret the root cause in this business environment.
JMC diagnostics: Look for the CPU spike, narrow down by selecting cpu-hot-worker, and analyze the sampled thread state and Hot Method caller states. Make sure to distinguish between self-time and inclusive time: the expensive caller might have offloaded its processing to a child method. Look at the lock and I/O events over the same period before blaming request latency on computing.
If the call stack is terminated, record another recording but with a larger stack depth setting, for example -XX:FlightRecorderOptions=stackdepth=128 when launching the JVM. A deeper stack view will not help recover the missing frames from the recording. A deeper captured stack can increase the costs of recording and the recording file size.
Best Use Case: Deep investigation of JFR problems involving CPU, GC, locks, and I/O events.
2. VisualVM
VisualVM is a free desktop tool licensed under the GPLv2 + Classpath license. It allows you to parse JFR records and connect to a running JVM simply by installing a compatible version.
Key Features
- Integration of JFR analysis and real-time monitoring
- Processor/Memory Profiling + Thread and heap analysis
- The basic function of JFR is built into the core tool
- Recording control and streaming functions must be expanded with extensions (version confirmation required)
Fig: VisualVM’s call tree identifies the hotMethod() method as the dominant sampled method in the cpu-hot-worker thread.
What the Results Tell Us
This screenshot shows the offline analysis cpu-spike-02.jfr. The call tree hotMethod() processor sampling shows the processing time of 89,804 milliseconds (99.9%), and the 89,852 ms total sample time for the worker thread are immediately apparent.
This popular approach is straightforward to implement. However, the percentage reported is only a relative value in the current call log area, and the measured time is just an estimated value of the sampling view. Don’t confuse these two numbers with the overall CPU utilization rate of the application or the number of actual clock cycles. Recording and sampling checks can be used to replicate workflows, but it is the engineer’s ability to drill down to the root cause.
Best Use Case: Engineers who wish to incorporate JFR analysis into their existing JVM troubleshooting processes.
3. async-profiler
async-profiler is an Apache-2.0-licensed open source sampling profiler with stable versions of Linux and macOS. Please install it on a supported host and configure process profiling permissions.
Key Features
- Specialized sampling profiling of CPU, allocations, and locks.
- Native and kernel stack traces, along with Java stack traces, on supported platforms.
- Scriptable sampling of incidents requiring repeatable profiling.
- JFR recordings that can be converted into an interactive HTML flame graph.
Fig: The async-profiler flame graph highlights hotMethod as the dominant sampled method during the WSL2 CPU load test.
What the Results Tell Us
We converted the separate WSL2 JFR recording into an interactive HTML flame graph. In this profile, hotMethod accounted for 1,875 samples, or 99.95% of the displayed samples.
For those who are familiar with reading stack profiles, this provides a clear starting point for analysis. Find out which questions a stored event can answer in a profile and whether the app context is overloaded or as expected.
Best Use Case: Engineers who need targeted, scriptable profiling, especially when the details of the initial implementation are important.
4. yCrash JFRPlayer
yCrash JFRPlayer can analyze JFR record files uploaded to your browser. Its official documentation explains two deployment options: cloud and on-premises deployment. Uploading to the cloud speeds up the initial installation, but private deployments require additional configuration. Check your current licenses, download limits, and pricing as needed for deployment.
Key Features
- Browser-based analysis of the uploaded JFR files, either in the cloud or on-premises.
- Template-based search, REST API, and archived reports.
- Compare multiple reports.
- Use the power of AI to identify issues with the help of the product’s AI Overview, suggesting the busiest method and thread.
- First, locate the issues; then, let engineers investigate and discuss them.
Fig: yCrash JFRPlayer’s AI Overview identifies the CPU-intensive method and worker thread for further investigation.
What the Results Tell Us
In our test records, the AI Overview module accurately identified the CpuSpikeDemo.hotMethod(long) method and the cpu-hot-worker thread and identified 5,612 method samples. This allows the analyst to obtain a specific study object instead of relying solely on the interpretation of the chart.
The summary correctly identifies the busy methods, but requires human interpretation. The percentage is a sampled value and not a direct measurement of the CPU cycle.
While the loop was deliberately created for the test, this recording cannot detect unexpected performance degradation in the production environment, nor can it be used to recommend optimizations.
The technical documentation for the tool states that first, the events are organized into nested sets forming a structured finding before being placed in context for large language models. By providing evidence-backed context, the findings enable more accurate interpretation by AI, requiring human validation nevertheless. The FAQ makes a distinction between the language used to describe deterministic analysis results and that used for AI, which may differ.
The analysis report also enables the inspection of the entire call tree for a particular method in the form of a flame graph.
Fig: The yCrash JFRPlayer flame graph shows the call path leading to hotMethod, providing context for investigating the CPU hotspot.
Best Use Case: Teams who value wizard-based troubleshooting, automatic problem detection, and browser-based reporting.
For a practical walkthrough, check out the Innovation in JFR Analysis with AI webinar, where you can find the presentation slides, webinar recording, and Q&A session.
Java Flight Recorder Tools Compared: Configuration, Cost, Automation, and Use Cases
This table summarizes the practical tools. The speed of the base case is explained by the workflow characteristics, as the examination time is not measured.
| Tool | Configuration | Cost | Automation Level | Speed/Workflow | Optimum Operating Mode |
|---|---|---|---|---|---|
| JMC | Desktop installation with a compatible JDK | Free OpenJDK distributions; check vendor terms | Analyze rules and headless APIs | Detailed view and rule finding; Depends on skill and scope | Deep JFR exploration |
| VisualVM | Desktop Installation Required; Open Recording File or Connect to JVM | Free; GPLv2 and Classpath Exception | Apply Recording/Sampling Control and Command Line Options | Direct Call Tree Inspection; Engineers Correlate Broad Causes | Common JVM Troubleshooting |
| async-profiler | Supported hosts and required profiling rights | Free; Apache 2.0 license | Script Collection | Java, native, and supported kernel stack profiling | Target processor, allocation, and lock profiling |
| JFRPlayer | Cloud upload or configured private deployment | Price unconfirmed; current condition requires vendor to confirm | Pattern detection, AI interpretation, REST API integration | Detection results lead to investigation; recommendations must be validated | Troubleshooting and Sharing Report |
Which JFR Analysis Tool Should You Choose?
All four workflows revealed the deliberately CPU-intensive method. The choice of the tool depends on what the next step is going to be.
When investigating the behavior of the processor, it is essential to create profiling reports (if required) and analyze them in detail: the execution status of each method, caller, and chains. Memory management and GC-related checks are equally important and focus on such aspects as memory allocation and GC events. If there are any questions about the storage of the object, it is necessary to get a heap dump. For contention analysis, make sure that the stored data contains appropriate tracking information and/or pending events before the assessment. This memory and contention analysis advice is based only on official specifications and differs from the results of this actual confirmation.
During the team review, consider whether your colleagues have easy access to evidence to support their arguments and understand the logical evolution. Whether it’s through web browser reports, various APIs, locally stored analytics files, or automated batch processing, there are several ways to get the job done.
Each tool complements the other. In a regular survey, it can be used to collect data with an async-profiler, automatically check for detected issues, and dig deeper into specific events with JMC. No matter which tool you choose, the most important thing is whether the event data you receive helps you resolve fundamental questions.
Conclusion: Choosing the Right Java Flight Recorder Analysis Tool
In this article, we compared four different workflows using a controlled CPU workload. The crucial difference is how different types of tools lead to the root of the problem, not whether superficial hotspots can be displayed.
- JMC: a highly scalable analytical tool that enables detailed tracking of individual events
- VisualVM: a practical option for performing JFR analysis in a versatile JVM toolset
- async-profiler: a powerful tool optimized for acquiring specific profiles and exploring performance paths
- JFRPlayer: very useful for research, production, and teamwork with guidance, but re-confirmation of evidence is essential
After making changes to the application, re-record under similar loads. Compare CPU usage, throughput, and response times to the profile to make sure that the problem is solved with the changes made.
More detailed comparisons can be found in the Java Mission Control (JMC) vs. yCrash JFR Player comparison article.

