Skip to main content
Redhat Developers  Logo
  • Products

    Featured

    • Red Hat Enterprise Linux
      Red Hat Enterprise Linux Icon
    • Red Hat OpenShift AI
      Red Hat OpenShift AI
    • Red Hat Enterprise Linux AI
      Linux icon inside of a brain
    • Image mode for Red Hat Enterprise Linux
      RHEL image mode
    • Red Hat OpenShift
      Openshift icon
    • Red Hat Ansible Automation Platform
      Ansible icon
    • Red Hat Developer Hub
      Developer Hub
    • View All Red Hat Products
    • Linux

      • Red Hat Enterprise Linux
      • Image mode for Red Hat Enterprise Linux
      • Red Hat Universal Base Images (UBI)
    • Java runtimes & frameworks

      • JBoss Enterprise Application Platform
      • Red Hat build of OpenJDK
    • Kubernetes

      • Red Hat OpenShift
      • Microsoft Azure Red Hat OpenShift
      • Red Hat OpenShift Virtualization
      • Red Hat OpenShift Lightspeed
    • Integration & App Connectivity

      • Red Hat Build of Apache Camel
      • Red Hat Service Interconnect
      • Red Hat Connectivity Link
    • AI/ML

      • Red Hat OpenShift AI
      • Red Hat Enterprise Linux AI
    • Automation

      • Red Hat Ansible Automation Platform
      • Red Hat Ansible Lightspeed
    • Developer tools

      • Red Hat Trusted Software Supply Chain
      • Podman Desktop
      • Red Hat OpenShift Dev Spaces
    • Developer Sandbox

      Developer Sandbox
      Try Red Hat products and technologies without setup or configuration fees for 30 days with this shared Openshift and Kubernetes cluster.
    • Try at no cost
  • Technologies

    Featured

    • AI/ML
      AI/ML Icon
    • Linux
      Linux Icon
    • Kubernetes
      Cloud icon
    • Automation
      Automation Icon showing arrows moving in a circle around a gear
    • View All Technologies
    • Programming Languages & Frameworks

      • Java
      • Python
      • JavaScript
    • System Design & Architecture

      • Red Hat architecture and design patterns
      • Microservices
      • Event-Driven Architecture
      • Databases
    • Developer Productivity

      • Developer productivity
      • Developer Tools
      • GitOps
    • Secure Development & Architectures

      • Security
      • Secure coding
    • Platform Engineering

      • DevOps
      • DevSecOps
      • Ansible automation for applications and services
    • Automated Data Processing

      • AI/ML
      • Data Science
      • Apache Kafka on Kubernetes
      • View All Technologies
    • Start exploring in the Developer Sandbox for free

      sandbox graphic
      Try Red Hat's products and technologies without setup or configuration.
    • Try at no cost
  • Learn

    Featured

    • Kubernetes & Cloud Native
      Openshift icon
    • Linux
      Rhel icon
    • Automation
      Ansible cloud icon
    • Java
      Java icon
    • AI/ML
      AI/ML Icon
    • View All Learning Resources

    E-Books

    • GitOps Cookbook
    • Podman in Action
    • Kubernetes Operators
    • The Path to GitOps
    • View All E-books

    Cheat Sheets

    • Linux Commands
    • Bash Commands
    • Git
    • systemd Commands
    • View All Cheat Sheets

    Documentation

    • API Catalog
    • Product Documentation
    • Legacy Documentation
    • Red Hat Learning

      Learning image
      Boost your technical skills to expert-level with the help of interactive lessons offered by various Red Hat Learning programs.
    • Explore Red Hat Learning
  • Developer Sandbox

    Developer Sandbox

    • Access Red Hat’s products and technologies without setup or configuration, and start developing quicker than ever before with our new, no-cost sandbox environments.
    • Explore Developer Sandbox

    Featured Developer Sandbox activities

    • Get started with your Developer Sandbox
    • OpenShift virtualization and application modernization using the Developer Sandbox
    • Explore all Developer Sandbox activities

    Ready to start developing apps?

    • Try at no cost
  • Blog
  • Events
  • Videos

How to monitor Quarkus native executables with JFR

Start using JFR to debug, profile, and monitor Quarkus native executables

June 13, 2023
Robert Toyonaga
Related topics:
JavaKubernetesQuarkus
Related products:
Red Hat build of OpenJDKRed Hat build of Quarkus

Share:

    This article will explain how to profile and monitor Quarkus native executables using JDK Flight Recorder (JFR). It will provide a step-by-step guide through building, running, and inspecting a Quarkus-native executable with JFR. You will also learn about the current features available, depending on your GraalVM/Mandrel version and how you can start using them.

    Prerequisites

    This article is meant for those already somewhat familiar with Quarkus native executables and who want to know the extent of JFR support in native mode and how to enable it.

    To get the most out of this article, you should already be familiar with building Quarkus native applications. If you're just getting started, you can learn how to build Quarkus Java applications and Quarkus native applications. This article will walk you through everything from scratch. But we recommend reading the previous two articles, Improvements to Native Image JFR support in GraalVM for JDK 20 and Implementing JDK Flight Recorder support for GraalVM Native Image.

    It is also good to have some experience using JFR and inspecting recordings using Java Mission Control (JMC). Again, this is not strictly necessary because all the steps will be covered here, but it is good background knowledge to have.

    GraalVM version

    For features such as stack traces, allocation events, container events, some thread events, and event streaming, you need GraalVM for JDK 17/JDK 20 or Mandrel 23. If you are using the Red Hat build of Quarkus, Mandrel 22.3 is the version that is officially supported. That version of Native Image does not include some of the features available in the latest GraalVM / Mandrel release, but custom JFR events and some useful built-in VM inspection events are still available. Please refer to the table at the end of this article for a summary of features included for each version.

    You can download GraalVM and Mandrel versions.

    How to build, run, and inspect with JFR

    Use the -Dquarkus.native.monitoring=jfr option when building your native executable. Then, use -XX:+FlightRecorder -XX:StartFlightRecording=filename=recording.jfr when running your native executable.

    For example, if using the hibernate-orm-quickstart, follow these steps:

    1. Specify what version of GraalVM/Mandrel to use.

    export GRAALVM_HOME=<Path to Mandrel or GraalVM>

    2. Build the native executable.

    ./mvnw package -Dnative -Dquarkus.native.monitoring=jfr
    

    Notice that here we use -Dquarkus.native.monitoring to specify we want to add JFR features to the image build.

    3. Start up the database that the Quarkus app will use. This step is exactly the same as in the quick start tutorial.

    docker run --rm=true --name quarkus_test -e POSTGRES_USER=quarkus_test -e POSTGRES_PASSWORD=quarkus_test -e POSTGRES_DB=quarkus_test -p 5432:5432 postgres:13.3

    4. Run the binary which is generated in the /target directory.

    ./target/hibernate-orm-quickstart-1.0.0-SNAPSHOT-runner -XX:+FlightRecorder -XX:StartFlightRecording=filename=recording.jfr

    You can also pass other Flight Recorder settings, such as providing a duration or specifying a configuration file:

    -XX:StartFlightRecording=settings=Path/To/YourSettings.jfc,duration=60s,filename=recording.jfr

    5. Interact with the application at http://0.0.0.0:8080/. Once you are done, use Ctrl+C to stop the Quarkus application.

    6. A JFR snapshot file named recording.jfr should have been generated in the current working directory. Let's open it with Java mission control (JMC), as shown in Figure 1.

    The inspect recording in JMC.
    Figure 1. The recording.jfr opened in JMC.

    Example use case: Profiling object allocations

    In Hotspot, there are two JFR events used to determine where your application is doing most of its allocations as well as their sizes: jdk.ObjectAllocationInNewTLAB and jdk.ObjectAllocationOutsideTLAB. However, in SubstrateVM (the runtime environment that Native Image uses) new allocations that won't fit in the current thread local allocation buffer (TLAB) are always allocated in a new TLAB (at the time of GraalVM for JDK 17/20). For this reason, only jdk.ObjectAllocationInNewTLAB exists in Native Image.

    Similarly to Hotspot, this event does not account for every single allocation. Instead, as the name suggests, it's only emitted when the allocation slow path is taken and a new TLAB is required. This effective sampling greatly reduces the overhead of using this event. However, there is still large and indeterministic overhead to enabling this event, which is why it is disabled by default (similar to Hotspot). It is only meant for profiling/debugging purposes, not for continuous monitoring. To enable this event, you should provide a settings configuration (.jfc file) when running your executable with JFR. You must enable the event in the configuration file as follows:

      <event name="jdk.ObjectAllocationInNewTLAB">
        <setting name="enabled" control="gc-enabled-high">true</setting>
        <setting name="stackTrace">true</setting>
      </event>

    Alternatively, you can use the preset settings file profile.jfc, which already has the event enabled.

    Running your application will now look like this:

    ./target/hibernate-orm-quickstart-1.0.0-SNAPSHOT-runner -XX:+FlightRecorder -XX:StartFlightRecording=settings=<Path/To/your.jfc>,filename=recording.jfr
    

    After running the executable and opening the JFR file in JMC, you should be able to see information in the Memory tab (Figure 2).

    Profile and Monitor Quarkus Native Executables: JMC memory tab
    Figure 2. Viewing allocations in the Memory tab.

    Current JFR features

    The following sections describe the new JFR support in GraalVM for JDK 17/JDK 20 and Mandrel 23. Refer to the table at the end of this article for a summary of features in the latest GraalVM release versus Mandrel 22.3.

    Events

    Implemented events are as close to the versions available in OpenJDK as possible, providing the expected event fields, thread info, and stack trace data. There are events available in OpenJDK that are not applicable to ahead-of-time compiled native executables and have been purposefully excluded. Such examples include events related to compilation and class loading. Events that instrument the VM (i.e., thread, monitor, and safe point events) have been recreated in the SubstrateVM internal code to replicate the same behavior as in HotSpot. Events that are implemented in OpenJDK through bytecode instrumentation are not yet available in Native Image (i.e., file, exception, and socket events).

    You can find the most up-to-date list on GitHub. You can also refer to a useful list of OpenJDK JFR events.

    Method profiling

    Similar to OpenJDK, profiling is done via a sampling-based approach with the jdk.ExecutionSample event. There are 2 sampling methods that can be toggled with command line arguments. If the argument -H:+SignalHandlerBasedExecutionSampler is provided at image build time, the SIGPROF based sampler will be used. Otherwise, the recurring callback sampler will be used. If using the SIGPROF sampler, your build command will look like this:

    ./mvnw package -Dnative -Dquarkus.native.monitoring=jfr -Dquarkus.native.additional-build-args=-H:+SignalHandlerBasedExecutionSampler

    Method sampling can help you determine where your application is spending most of its time, identifying hot methods (Figure 3).

    Profile and Monitor Quarkus Native Executables: Method profiling with flame graph
    Figure 3. The method profiling page.

    Event streaming

    Event streaming was introduced to JFR in JDK 14. As of GraalVM for JDK 17/JDK 20, it is experimentally supported in Native Image. It allows an application to subscribe to a stream of its events while a recording is still in progress. Previously, to access JFR data, a recording file had to be dumped, then parsed. Similar to OpenJDK, event streaming in Native Image has two main components, the consumer code that parses JFR disk repository chunks and performs call backs, and the producer code that periodically updates the disk repository. The consumer code is reused from OpenJDK, while the producer code had to be re-implemented to work in SubstrateVM.

    This re-implemented producer component allows for the flushing of active JFR chunk data to the JFR disk repository. Flushing in-progress data before the chunk is complete is the key component that allows for more frequent updates. The following example illustrates the setting up of a stream and registering a callback, triggered when a monitor wait event is emitted. The callback prints the monitor's class, and current thread does not block when the asynchronous stream starts.

    var rs = new RecordingStream();
    rs.enable("jdk.JavaMonitorWait");
    rs.onEvent("jdk.JavaMonitorWait", event -> {
        System.out.println(event.<RecordedClass>getValue("monitorClass").getName());
    });
    rs.startAsync();

    Summary of features by version

    Feature

    GraalVM for JDK17 and JDK 20, and Mandrel 23

    Mandrel 22.3

    Event streaming Supported (experimental) Not supported
    Stack traces Supported Not supported
    Method Profiling Supported Not supported
    Custom Events Supported Supported
    Control recordings via recording API Supported Supported

    ActiveRecording

    ActiveSetting

    DataLoss

    ExecuteVMOperation

    GarbageCollection

    GCPhasePause

    InitialEnvironmentVariable

    InitialSystemProperty

    JavaMonitorEnter

    JavaMonitorWait

    JavaThreadStatistics

    JVMInformation

    OSInformation

    PhysicalMemory

    SafepointBegin

    SafepointEnd

    ThreadEnd

    ThreadSleep

    ThreadStart

    Supported Supported

    ContainerCPUThrottling

    ContainerCPUUsage

    ContainerConfiguration

    ContainerIOUsage

    ContainerMemoryUsage

    ExecutionSample

    JavaMonitorInflate

    ObjectAllocationInNewTLAB

    ThreadPark

    Supported Not supported

    Using JFR for Quarkus-native executables

    This article explained how to profile and monitor Quarkus-native executables using JDK Flight Recorder (JFR). We hope you were able to easily follow the steps for building, running, and inspecting Quarkus native executables with JFR. Now, you can utilize the current features, depending on your GraalVM/Mandrel version. Comment below if you have questions. We welcome your feedback.

    Last updated: September 19, 2023

    Related Posts

    • How to build automated JFR rules with Cryostat 2.1's new UI

    • Manage JFR across instances with Cryostat and GraphQL

    • Access JFR data faster with Cryostat 2.1's new download APIs

    • Set up JDK Mission Control with Red Hat Build of OpenJDK

    Recent Posts

    • Integrate Red Hat AI Inference Server & LangChain in agentic workflows

    • Streamline multi-cloud operations with Ansible and ServiceNow

    • Automate dynamic application security testing with RapiDAST

    • Assessing AI for OpenShift operations: Advanced configurations

    • OpenShift Lightspeed: Assessing AI for OpenShift operations

    What’s up next?

    Quarkus for Spring Developers

    Learn how to optimize Java for today’s compute and runtime demands with Quarkus. Quarkus for Spring Developers introduces Quarkus to Java developers, with a special eye for helping those familiar with Spring’s conventions make a quick and easy transition.

    Get the e-book
    Red Hat Developers logo LinkedIn YouTube Twitter Facebook

    Products

    • Red Hat Enterprise Linux
    • Red Hat OpenShift
    • Red Hat Ansible Automation Platform

    Build

    • Developer Sandbox
    • Developer Tools
    • Interactive Tutorials
    • API Catalog

    Quicklinks

    • Learning Resources
    • E-books
    • Cheat Sheets
    • Blog
    • Events
    • Newsletter

    Communicate

    • About us
    • Contact sales
    • Find a partner
    • Report a website issue
    • Site Status Dashboard
    • Report a security problem

    RED HAT DEVELOPER

    Build here. Go anywhere.

    We serve the builders. The problem solvers who create careers with code.

    Join us if you’re a developer, software engineer, web designer, front-end designer, UX designer, computer scientist, architect, tester, product manager, project manager or team lead.

    Sign me up

    Red Hat legal and privacy links

    • About Red Hat
    • Jobs
    • Events
    • Locations
    • Contact Red Hat
    • Red Hat Blog
    • Inclusion at Red Hat
    • Cool Stuff Store
    • Red Hat Summit

    Red Hat legal and privacy links

    • Privacy statement
    • Terms of use
    • All policies and guidelines
    • Digital accessibility

    Report a website issue