Skip to content

Conversation

@andrewazores
Copy link
Member

@andrewazores andrewazores commented Dec 19, 2025

Related to cryostatio/cryostat#643

Early draft. This includes a direct Maven dependency on async-profiler and some bootstrapping of it by the Cryostat Agent. That will need to be replaced by dynamic lookups of the async-profiler MXBean (or bean proxy) and no dependency on any async-profiler artifact. It will be up to the end user to get the correct async-profiler for their platform and architecture and attach that to their application (probably via -javaagent, but anything will work so long as the MXBean ends up present).

Related: async-profiler/async-profiler#1628


async-profiler nightly builds as of async-profiler/async-profiler@bf84fad include async-profiler/async-profiler#1628 , which makes it so that when attaching the async-profiler.jar as a -javaagent to a target application, the AsyncProfilerMXBean will be automatically registered in the target's platform (local) MBean server. If the Cryostat Agent is also attached to the same target then it will be able to detect the AsyncProfilerMXBean and provide integration functionality. This should land in async-profiler's upcoming feature release. Testing can also be done with any other sample application that has custom code added (the old way) to register the AsyncProfilerMXBean, so long as the async-profiler version is not severely outdated.

Manual testing of this integration can be done by downloading the async-profiler.jar from the nightly release above, along with the appropriate os/arch distribution of the libasyncProfiler.so . This can be combined into the https://github.com/cryostatio/test-applications/tree/main/quarkus-agent with the following patch:

diff --git a/quarkus-agent/src/main/docker/Dockerfile.jvm b/quarkus-agent/src/main/docker/Dockerfile.jvm
index c982b4e..e4aabec 100644
--- a/quarkus-agent/src/main/docker/Dockerfile.jvm
+++ b/quarkus-agent/src/main/docker/Dockerfile.jvm
@@ -80,11 +80,12 @@ FROM registry.access.redhat.com/ubi8/openjdk-17:latest
 ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en'
 ENV CRYOSTAT_AGENT=cryostat-agent-shaded.jar
 ENV JMC_AGENT=jmc-agent.jar
+ENV ASYNC_PROFILER_AGENT=async-profiler.jar
 
 EXPOSE 10010 9097
 USER 185
 ENV AB_JOLOKIA_OFF=""
-ENV JAVA_OPTS_APPEND="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager -Dcom.sun.management.jmxremote.port=9097 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -javaagent:/deployments/app/cryostat-agent.jar -javaagent:/deployments/app/$JMC_AGENT"
+ENV JAVA_OPTS_APPEND="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager -Dcom.sun.management.jmxremote.port=9097 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -javaagent:/deployments/app/$ASYNC_PROFILER_AGENT -javaagent:/deployments/app/cryostat-agent.jar -javaagent:/deployments/app/$JMC_AGENT"
 ENV JAVA_APP_JAR="/deployments/quarkus-run.jar"
 
 # We make four distinct layers so if there are application changes the library layers can be re-used
@@ -93,6 +94,9 @@ COPY --chown=185 target/quarkus-app/*.jar /deployments/
 COPY --chown=185 target/quarkus-app/app/ /deployments/app/
 COPY --chown=185 target/quarkus-app/quarkus/ /deployments/quarkus/
 
+COPY --chown=185 src/main/docker/extras/async-profiler/libasyncProfiler.so /usr/lib64/libasyncProfiler.so
+COPY --chown=185 src/main/docker/extras/async-profiler/async-profiler.jar /deployments/app/async-profiler.jar
+
 COPY --chown=185 target/dependency/$CRYOSTAT_AGENT /deployments/app/cryostat-agent.jar
 COPY --chown=185 target/dependency/$JMC_AGENT /deployments/app/$JMC_AGENT
 # COPY --chown=185 target/quarkus-app/lib/main/io.cryostat.cryostat-agent-*.jar /deployments/app/$CRYOSTAT_AGENT

and placing the downloaded async-profiler.jar and libasyncProfiler.so into src/main/docker/extras/async-profiler in the quarkus-agent test application.

Otherwise, I have prepared a test image which can be used directly with the smoketest:

$ export QUARKUS_TEST_IMAGE=quay.io/andrewazores/quarkus-cryostat-agent:async-profiler-1

Combine any method of obtaining an async-profiler equipped test application with the Cryostat and cryostat-web PRs and run ./smoktest.bash -O -t quarkus-cryostat-agent:

image
$ jfr summary quarkus-cryostat-agent_e353cfac-9d10-4377-b7fd-61d0337c74f5.asprof.jfr 

 Version: 2.0
 Chunks: 1
 Start: 2026-01-06 15:03:38 (UTC)
 Duration: 10 s

 Event Type                          Count  Size (bytes) 
=========================================================
 jdk.NativeLibrary                      31          2344
 jdk.InitialSystemProperty              25          1507
 jdk.ActiveSetting                      24           791
 jdk.CPULoad                             9           189
 jdk.ExecutionSample                     2            29
 jdk.Metadata                            1          9437
 jdk.Checkpoint                          1          1479
 jdk.ActiveRecording                     1            85
 jdk.OSInformation                       1           110
 jdk.CPUInformation                      1           366
 jdk.JVMInformation                      1           893
 jdk.GCHeapSummary                       1            47
 jdk.ObjectAllocationInNewTLAB           0             0
 jdk.ObjectAllocationOutsideTLAB         0             0
 jdk.JavaMonitorEnter                    0             0
 jdk.ThreadPark                          0             0
 jdk.MethodTrace                         0             0
 profiler.Log                            0             0
 profiler.Window                         0             0
 profiler.LiveObject                     0             0
 profiler.WallClockSample                0             0
 profiler.Malloc                         0             0
 profiler.Free                           0             0
 profiler.UserEvent                      0             0
 profiler.ProcessSample                  0             0
 profiler.NativeLock                     0             0

Currently this implementation still uses an Agent HTTP invoke context and internally interfaces with the AsyncProfilerMXBean, so that the Agent can perform additional non-MXBean behaviours such as creating a disk repository for async-profiler dumps and listing or retrieving files from that disk repository. This functionality is not implemented by the AsyncProfilerMXBean, so although it's possible for Cryostat to interact with that MXBean directly either via JMX or via the Agent's MBean invoke context, it would not support all of the features we want to implement. Perhaps in the future we can work with the async-profiler team to enhance the Java side of its API and MXBean so that the remote management capabilities are a bit more fleshed out, if they are willing to accept these kinds of changes, and we can integrate directly via MXBean invoke (either JMX or Cryostat Agent HTTP).

@andrewazores andrewazores added feat New feature or request safe-to-test labels Dec 19, 2025
@github-actions github-actions bot added the needs-triage Needs thorough attention from code reviewers label Dec 19, 2025
@andrewazores andrewazores removed the needs-triage Needs thorough attention from code reviewers label Dec 19, 2025
@andrewazores andrewazores changed the title feat(async-profiler): prototyping feat(async-profiler): basic integration Jan 7, 2026
@andrewazores andrewazores marked this pull request as ready for review January 7, 2026 16:22
@andrewazores andrewazores requested a review from a team January 7, 2026 16:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feat New feature or request safe-to-test

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant