JFR (Java Flight Recorder)

JFR Java API

  • JDK Flight Recorder, The Programmatic Way

    • Control Flight Recorder

      There are multiple ways to control JFR sessions: jcmd, JMX, JVM arguments.

      Handling sessions with API is an extra option offering you even more flexibility.

    • Read events from JFR binary files

      This can be handy if you want to build automated reporting or integrate JFR with your monitoring stack.

      Custom processing of recordings is also essential for the next use case - custom events.

    • Create application-specific Flight Recorder events

      You can leverage JFR infrastructure to produce events specific to your applications.

      Features such as periodic events and thresholds are also available for custom events.

JMC - JFR Recording

JFR Recording - Automated Analysis Results

JFR Recording - Java Application

JFR Recording - Threads

  • (Legacy) Threads

JFR Recording - Memory

  • Live Objects

JFR Recording - Lock Instances

JFR Recording - File I/O

JFR Recording - Socket I/O

JFR Recording - Method Profiling

JFR Recording - Exceptions

JFR Recording - Thread Dumps

JFR Recording - JVM Internals

JFR Recording - Garbage Collections

JFR Recording - GC Configuration

JFR Recording - GC Summary

JFR Recording - Compilations

  • Code Cache

JFR Recording - Class Loading

JFR Recording - VM Operations

JFR Recording - TLAB Allocations

alt text

Thread-Local Allocation Buffer

Each thread has a dedicated region where it allocates objects. When objects are allocated directly in a shared space such as eden, some thread synchronization is required to manage the free-space pointers within that space. By setting up each thread with its own dedicated allocation area, the thread needn’t perform any synchronization when allocating objects.

Large objects cannot be allocated within a TLAB, and must be allocated directly from the heap, which requires extra time because of the synchronization.

As a TLAB becomes full, no more allocation can be made in it, and there are 2 options for JVM:

  • JVM can retire a full TLAB, as it is just a section within eden, the retired TLAB will be cleaned at the next young collection and can be reused subsequently.
  • JVM can allocate the object directly on the heap and keep the existing TLAB.

The size of a TLAB is based on 3 factors:

  1. The number of threads in the applications
  2. The size of eden
  3. The allocation rate of threads

Applications that benefit from tuning the TLAB parameters:

  • Applications that allocate a lot of large objects
  • Applications that have a relatively large number of threads compared to the size of eden

If a significant number of allocations occur outside of TLABs, we have 2 choices:

  • Reduce the size of the object being allocated
  • Adjust the TLAB sizing parameters

JFR Recording - Environment

JFR Recording - Environment

JFR Recording - Processes

JFR Recording - Processes

JFR Recording - Environment Variables

JFR Recording - System Properties

JFR Recording - Native Libraries

JFR Recording - Recording

JFR Recording - Constant Pools

JFR Recording - Event Browser

JFR

JFR Event

Event - jdk.JVMInformation

jdk.JVMInformation {
  startTime = 22:08:08.107 (2025-10-23)
  jvmName = "OpenJDK 64-Bit Server VM"
  jvmVersion = "OpenJDK 64-Bit Server VM (21.0.8+9-LTS) for windows-amd64 JRE (21.0.8+9-LTS), built on 2025-07-15T00:00:00Z by "admin" with MS VC++ 17.7 (VS2022)"
  jvmArguments = "-javaagent:C:\Users\Takechiyo\AppData\Local\JetBrains\IntelliJIdea2025.2\captureAgent\debugger-agent.jar=file:///C:/Temp/capture12586928883480251180.props -ea -Didea.test.cyclic.buffer.size=4194304 -javaagent:C:\Users\Takechiyo\AppData\Local\Programs\IntelliJ IDEA Ultimate\lib\idea_rt.jar=57548 -Dkotlinx.coroutines.debug.enable.creation.stack.trace=false -Ddebugger.agent.enable.coroutines=true -Dkotlinx.coroutines.debug.enable.flows.stack.trace=true -Dkotlinx.coroutines.debug.enable.mutable.state.flows.stack.trace=true -Dfile.encoding=UTF-8 -Dsun.stdout.encoding=UTF-8 -Dsun.stderr.encoding=UTF-8"
  jvmFlags = N/A
  javaArguments = "com.intellij.rt.junit.JUnitStarter -ideVersion5 -junit5 cq.playground.spring.microservice.rest.profiling.ProfilingEventTest"
  jvmStartTime = 22:08:06.429 (2025-10-23)
  pid = 29440
}

JFR Event Streaming