Re: RFR: 8257967: JFR: Events for loaded agents [v10]
On Wed, 22 Mar 2023 09:18:51 GMT, David Holmes wrote: >> src/hotspot/share/prims/jvmtiEnvBase.hpp line 166: >> >>> 164: >>> 165: const void* get_env_local_storage() { return _env_local_storage; } >>> 166: >> >> Why was this change/move necessary? Do I miss anything? > > It is now public, not protected. I see, thanks. - PR Review Comment: https://git.openjdk.org/jdk/pull/12923#discussion_r1155048753
Re: RFR: 8257967: JFR: Events for loaded agents [v10]
On Tue, 14 Mar 2023 12:22:16 GMT, Markus Grönlund wrote: >> n.b. that also applies for accesses/updates to field _next. > > I wanted all accesses to use the iterator. The only access is given to the > iterator and AgentList by way of being friends. No need to expose more. I updated all external access to use getters/setters. - PR Review Comment: https://git.openjdk.org/jdk/pull/12923#discussion_r1153703241
Re: RFR: 8257967: JFR: Events for loaded agents [v10]
On Tue, 14 Mar 2023 12:26:16 GMT, Markus Grönlund wrote: > I've had a good look through now and have a better sense of the refactoring. > Seems good. > > I'll wait for any tweaks before hitting the approve button though. > > Thanks Moving the loading logic to the agent.cpp module was a bit harder than I initially thought. It also exposed a bug in how statically linked libraries were loaded - now fixed. Sorry for the large update. Thanks again for having a look. >> src/hotspot/share/prims/agentList.cpp line 542: >> >>> 540: >>> 541: // Invoke the Agent_OnAttach function >>> 542: JavaThread* THREAD = JavaThread::current(); // For exception macros. >> >> Nit: just use `current` rather than `THREAD` and don't use the exception >> macros. > > Ported as is but good point, will update. Updated - cheers. - PR Comment: https://git.openjdk.org/jdk/pull/12923#issuecomment-1490828465 PR Review Comment: https://git.openjdk.org/jdk/pull/12923#discussion_r1153703484
Re: RFR: 8257967: JFR: Events for loaded agents [v10]
On Tue, 14 Mar 2023 12:23:08 GMT, Markus Grönlund wrote: >> src/hotspot/share/prims/agentList.cpp line 419: >> >>> 417: const jint err = (*on_load_entry)(_vm, >>> const_cast(agent->options()), NULL); >>> 418: if (err != JNI_OK) { >>> 419: vm_exit_during_initialization("-Xrun library failed to init", >>> agent->name()); >> >> Do you need to be back in `_thread_in_vm` before exiting? > > Hmm. This was ported as is. I will double-check. Looks like there is no requirement to be in _thread_in_vm before invoking vm_exit_during_initialization(). vm_perform_shutdown_actions() will forcibly set the thread state to _thread_in_native (no transition). - PR Review Comment: https://git.openjdk.org/jdk/pull/12923#discussion_r1153243069
Re: RFR: 8257967: JFR: Events for loaded agents [v10]
On Tue, 21 Mar 2023 00:53:31 GMT, Serguei Spitsyn wrote: >> Markus Grönlund has updated the pull request incrementally with one >> additional commit since the last revision: >> >> more cleanup > > src/hotspot/share/prims/jvmtiEnvBase.hpp line 166: > >> 164: >> 165: const void* get_env_local_storage() { return _env_local_storage; } >> 166: > > Why was this change/move necessary? Do I miss anything? It is now public, not protected. - PR Review Comment: https://git.openjdk.org/jdk/pull/12923#discussion_r1144458026
Re: RFR: 8257967: JFR: Events for loaded agents [v10]
On Fri, 10 Mar 2023 10:43:23 GMT, Markus Grönlund wrote: >> 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" >> 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
Re: RFR: 8257967: JFR: Events for loaded agents [v10]
On Tue, 14 Mar 2023 12:26:16 GMT, Markus Grönlund wrote: >> I've had a good look through now and have a better sense of the refactoring. >> Seems good. >> >> I'll wait for any tweaks before hitting the approve button though. >> >> Thanks > >> I've had a good look through now and have a better sense of the refactoring. >> Seems good. >> >> >> >> I'll wait for any tweaks before hitting the approve button though. >> >> >> >> Thanks > > Thanks so much for taking a look. I realized that implementation details of > loading should probably reside in agent.cpp, not agentList.cpp. > > I am currently off on vacation and will update when back. Thanks also to > Andrew Dinn for comments. @mgronlun I'm looking at the fixes but it will take some time. - PR: https://git.openjdk.org/jdk/pull/12923
Re: RFR: 8257967: JFR: Events for loaded agents [v10]
On Mon, 13 Mar 2023 09:46:04 GMT, Andrew Dinn wrote: >> Markus Grönlund has updated the pull request incrementally with one >> additional commit since the last revision: >> >> more cleanup > > src/hotspot/share/jfr/metadata/metadata.xml line 1182: > >> 1180: > description="The time the JVM initialized the agent" /> >> 1181: > label="Initialization Time" description="The duration of executing the >> initialization method exported by the agent" /> >> 1182: > > @mgronlun A somewhat drive-by comment. It might be clearer if you renamed > these event fields and accessors, plus also the corresponding fields and > accessors in class Agent, as `initializationTime` and > `initializationDuration`. Makes sense. - PR: https://git.openjdk.org/jdk/pull/12923
Re: RFR: 8257967: JFR: Events for loaded agents [v10]
On Tue, 14 Mar 2023 06:01:05 GMT, David Holmes wrote: > I've had a good look through now and have a better sense of the refactoring. > Seems good. > > > > I'll wait for any tweaks before hitting the approve button though. > > > > Thanks Thanks so much for taking a look. I realized that implementation details of loading should probably reside in agent.cpp, not agentList.cpp. I am currently off on vacation and will update when back. Thanks also to Andrew Dinn for comments. - PR: https://git.openjdk.org/jdk/pull/12923
Re: RFR: 8257967: JFR: Events for loaded agents [v10]
On Mon, 13 Mar 2023 09:49:39 GMT, Andrew Dinn wrote: >> src/hotspot/share/prims/agentList.cpp line 64: >> >>> 62: void AgentList::add_xrun(const char* name, char* options, bool >>> absolute_path) { >>> 63: Agent* agent = new Agent(name, options, absolute_path); >>> 64: agent->_is_xrun = true; >> >> Why direct access of private field instead of having a setter like other >> parts of the Agent API? > > n.b. that also applies for accesses/updates to field _next. I wanted all accesses to use the iterator. The only access is given to the iterator and AgentList by way of being friends. No need to expose more. - PR: https://git.openjdk.org/jdk/pull/12923
Re: RFR: 8257967: JFR: Events for loaded agents [v10]
On Mon, 13 Mar 2023 06:22:21 GMT, David Holmes wrote: >> Markus Grönlund has updated the pull request incrementally with one >> additional commit since the last revision: >> >> more cleanup > > src/hotspot/share/prims/agent.cpp line 34: > >> 32: } >> 33: >> 34: static const char* allocate_copy(const char* str) { > > Why not just use `os::strdup`? Better alternative, thanks David. > src/hotspot/share/prims/agentList.cpp line 227: > >> 225: * store data in their JvmtiEnv local storage. >> 226: * >> 227: * Please see JPLISAgent.c in module java.instrument, see JPLISAgent.h >> and JPLISAgent.c. > > No need to mention the .c file twice. Good point. > src/hotspot/share/prims/agentList.cpp line 419: > >> 417: const jint err = (*on_load_entry)(_vm, >> const_cast(agent->options()), NULL); >> 418: if (err != JNI_OK) { >> 419: vm_exit_during_initialization("-Xrun library failed to init", >> agent->name()); > > Do you need to be back in `_thread_in_vm` before exiting? Hmm. This was ported as is. I will double-check. > src/hotspot/share/prims/agentList.cpp line 542: > >> 540: >> 541: // Invoke the Agent_OnAttach function >> 542: JavaThread* THREAD = JavaThread::current(); // For exception macros. > > Nit: just use `current` rather than `THREAD` and don't use the exception > macros. Ported as is but good point, will update. - PR: https://git.openjdk.org/jdk/pull/12923
Re: RFR: 8257967: JFR: Events for loaded agents [v10]
On Fri, 10 Mar 2023 10:43:23 GMT, Markus Grönlund wrote: >> 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" >> 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
Re: RFR: 8257967: JFR: Events for loaded agents [v10]
On Thu, 9 Mar 2023 09:29:41 GMT, Markus Grönlund wrote: >> src/hotspot/share/runtime/threads.cpp line 338: >> >>> 336: if (EagerXrunInit && Arguments::init_libraries_at_startup()) { >>> 337: create_vm_init_libraries(); >>> 338: } >> >> Not obvious where this went. Changes to the initialization order can be very >> problematic. > > Thanks, David. Two calls to launch XRun agents are invoked during startup, > and they depend on the EagerXrunInit option. The !EagerXrunInit case is > already located in create_vm(), but the EagerXrunInit was located as the > first entry in initialize_java_lang_classes(), which I thought was tucked > away a bit unnecessarily. > > I hoisted the EagerXrunInit case from initialize_java_lang_classes() up to > create_vm(). It's now the call just before initialize_java_lang_classes(). > > This made it clearer, i.e. to have both calls located directly in create_vm(). Thanks for clarifying. That makes sense. - PR: https://git.openjdk.org/jdk/pull/12923
Re: RFR: 8257967: JFR: Events for loaded agents [v10]
On Mon, 13 Mar 2023 06:29:11 GMT, David Holmes wrote: >> Markus Grönlund has updated the pull request incrementally with one >> additional commit since the last revision: >> >> more cleanup > > src/hotspot/share/prims/agentList.cpp line 64: > >> 62: void AgentList::add_xrun(const char* name, char* options, bool >> absolute_path) { >> 63: Agent* agent = new Agent(name, options, absolute_path); >> 64: agent->_is_xrun = true; > > Why direct access of private field instead of having a setter like other > parts of the Agent API? n.b. that also applies for accesses/updates to field _next. - PR: https://git.openjdk.org/jdk/pull/12923
Re: RFR: 8257967: JFR: Events for loaded agents [v10]
On Fri, 10 Mar 2023 10:43:23 GMT, Markus Grönlund wrote: >> 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" >> 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
Re: RFR: 8257967: JFR: Events for loaded agents [v10]
On Fri, 10 Mar 2023 10:43:23 GMT, Markus Grönlund wrote: >> 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" >> 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
Re: RFR: 8257967: JFR: Events for loaded agents [v10]
> 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" > 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)