JDK-8257967 : JFR: Events for loaded agents
  • Type: Enhancement
  • Component: hotspot
  • Sub-Component: jfr
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2020-12-09
  • Updated: 2024-02-09
  • Resolved: 2023-04-17
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 21
21 b19Fixed
Related Reports
Blocks :  
Relates :  
Relates :  
Relates :  
Relates :  
Description
Sometimes when going through customer recordings, it would be interesting to know if any agents have been loaded, and where from. A requestable event with all the agents that have been dynamically attached, at what time they were attached, and from where, would be helpful.
Comments
On AIX (when running test with fastdebug binaries) hundreds of jtreg tests fail after this. I created https://bugs.openjdk.org/browse/JDK-8306278 . For example a lot of jdk/jshell/ tests fail .
18-04-2023

looks like the code relies on os::dll_address_to_library_name returning a valid offset in non-error cases (see JvmtiAgentList::lookup ). However this is not always the case but optional, see os.hpp : // Locate DLL/DSO. On success, full path of the library is copied to // buf, and offset is optionally set to be the distance between addr // and the library's base address. On failure, buf[0] is set to '\0' // and offset is set to -1 (if offset is non-null). static bool dll_address_to_library_name(address addr, char* buf, int buflen, int* offset); On AIX , offset is set to -1 (the optional functionality is not supported).
18-04-2023

Changeset: 5c95bb1c Author: Markus Grönlund <mgronlun@openjdk.org> Date: 2023-04-17 10:25:36 +0000 URL: https://git.openjdk.org/jdk/commit/5c95bb1c5146e13dd213d5ca6e02e2a02ca0323e
17-04-2023

We are adding support to let JFR report on Agents. #### Design An Agent is a library that uses any instrumentation or profiling APIs. Most agents are started and initialized on the command line, but agents can also be loaded dynamically during runtime. Because command line agents initialize during the VM startup sequence, they add to the overall startup time latency in getting the VM ready. The events will report on the time the agent took to initialize. A JavaAgent is an agent written in the Java programming language, using the APIs in the package [java.lang.instrument](https://docs.oracle.com/en/java/javase/19/docs/api/java.instrument/java/lang/instrument/package-summary.html) A JavaAgent is sometimes called a JPLIS agent, where the acronym JPLIS stands for Java Programming Language Instrumentation Services. To report on JavaAgents, JFR will add the new event type jdk.JavaAgent and events will look similar to these two examples: // Command line jdk.JavaAgent { startTime = 12:31:19.789 (2023-03-08) name = "JavaAgent.jar" options = "foo=bar" dynamic = false initialization = 12:31:15.574 (2023-03-08) initializationTime = 172 ms } // Dynamic load jdk.JavaAgent { startTime = 12:31:31.158 (2023-03-08) name = "JavaAgent.jar" options = "bar=baz" dynamic = true initialization = 12:31:31.037 (2023-03-08) initializationTime = 64,1 ms } The jdk.JavaAgent event type is a JFR periodic event that iterates over running Java agents. For a JavaAgent event, the agent's name will be the specific .jar file containing the instrumentation code. The options will be the specific options passed to the .jar file as part of launching the agent, for example, on the command line: -javaagent: JavaAgent.jar=foo=bar. The "dynamic" field denotes if the agent was loaded via the command line (dynamic = false) or dynamically (dynamic = true) "initialization" is the timestamp the JVM invoked the initialization method, and "initializationTime" is the duration of executing the initialization method. "startTime" represents the time the JFR framework issued the periodic event; hence "initialization" will be earlier than "startTime". An agent can also be written in a native programming language using the [JVM Tools Interface (JVMTI)](https://docs.oracle.com/en/java/javase/19/docs/specs/jvmti.html). This kind of agent, sometimes called a native agent, is a platform-specific binary, sometimes referred to as a library, but here it means a .so or .dll file. To report on native agents, JFR will add the new event type jdk.NativeAgent and events will look similar to this example: jdk.NativeAgent { startTime = 12:31:40.398 (2023-03-08) name = "jdwp" options = "transport=dt_socket,server=y,address=any,onjcmd=y" dynamic = false initialization = 12:31:36.142 (2023-03-08) initializationTime = 0,00184 ms path = "c:\ade\github\openjdk\jdk\build\windows-x86_64-server-slowdebug\jdk\bin\jdwp.dll" } The layout of the event type is very similar to the jdk.JavaAgent event, but here the path to the native library is reported. The initialization of a native agent is performed by invoking an agent-specified callback routine. The "initialization" is when the JVM sent or would have sent the JVMTI VMInit event to a specified callback. "initializationTime" is the duration to execute that specific callback. If no callback is specified for the JVMTI VMInit event, the "initializationTime" will be 0. #### Implementation There has not existed a reification of a JavaAgent directly in the JVM, as these are built on top of the JDK native library, "instrument", using a many-to-one mapping. At the level of the JVM, the only representation of agents after startup is through JvmtiEnv's, which agents request from the JVM during startup and initialization — as such, mapping which JvmtiEnv belongs to what JavaAgent was not possible before. Using implementation details of how the JDK native library "instrument" interacts with the JVM, we can build this mapping to track what JvmtiEnv's "belong" to what JavaAgent. This mapping now lets us report the Java-relevant context (name, options) and measure the time it takes for the JavaAgent to initialize. When implementing this capability, it was necessary to refactor the code used to represent agents, AgentLibrary. The previous implementation was located primarily in arguments.cpp, and threads.cpp but also jvmtiExport.cpp. The refactoring isolates the relevant logic into two new modules, prims/agent.hpp and prims/agentList.hpp. Breaking out this code from their older places will help reduce the sizes of oversized arguments.cpp and threads.cpp. The previous two lists that maintained "agents" (JVMTI) and "libraries" (Xrun) were not thread-safe for concurrent iterations. A single list that allows for concurrent iterations is therefore introduced.
09-03-2023

Neat!
08-03-2023

A pull request was submitted for review. URL: https://git.openjdk.org/jdk/pull/12923 Date: 2023-03-08 12:41:15 +0000
08-03-2023

A pull request was submitted for review. URL: https://git.openjdk.org/jdk/pull/12460 Date: 2023-02-07 18:43:32 +0000
10-02-2023

This is a good idea, should have been implemented ten years ago. Agents loaded on the command line could be included as well.
10-12-2020