> Greetings, > > 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" > initialization = 12:31:15.574 (2023-03-08) > initializationTime = 172 ms > initializationMethod = "premain" > } > // Dynamic load > jdk.JavaAgent { > startTime = 12:31:31.158 (2023-03-08) > name = "JavaAgent.jar" > options = "bar=baz" > initialization = 12:31:31.037 (2023-03-08) > initializationTime = 64,1 ms > initializationMethod = "agentmain" > } > > 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 event will also detail which initialization method was invoked by the > JVM, "premain" for command line agents, and "agentmain" for agents loaded > dynamically. > > "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" > path = > "c:\ade\github\openjdk\jdk\build\windows-x86_64-server-slowdebug\jdk\bin\jdwp.dll" > dynamic = false > initialization = 12:31:36.142 (2023-03-08) > initializationTime = 0,00184 ms > } > > The layout of the event type is very similar to the jdk.JavaAgent event, but > here the path to the native library is reported, and there is also a > denotation if the agent was loaded via the command line (dynamic = false) or > dynamically (dynamic = true). > > The initialization of a native agent is performed by invoking an > agent-specified callback routine which is not detailed in the event (for > now). The "initialization" is the time 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. > > To implement this capability, it was necessary to refactor the code used to > represent agents, called 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 lists that maintain the agents (JVMTI) and libraries (JVMPI) are > not thread-safe for concurrent iterations. A single list that allows for > concurrent iterations is therefore introduced. > > Testing: jdk_jfr, tier 1 - 6 > > Thanks > Markus
Markus Grönlund has updated the pull request incrementally with two additional commits since the last revision: - remove JVMPI - cleanup ------------- Changes: - all: https://git.openjdk.org/jdk/pull/12923/files - new: https://git.openjdk.org/jdk/pull/12923/files/26172f0e..355d307c Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=12923&range=03 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=12923&range=02-03 Stats: 2 lines in 2 files changed: 0 ins; 0 del; 2 mod Patch: https://git.openjdk.org/jdk/pull/12923.diff Fetch: git fetch https://git.openjdk.org/jdk pull/12923/head:pull/12923 PR: https://git.openjdk.org/jdk/pull/12923