-
Notifications
You must be signed in to change notification settings - Fork 1.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support Java agent instrumentation in native image #8077
base: master
Are you sure you want to change the base?
Conversation
274d838
to
d8c5c50
Compare
How does that work for modules? As far as I know, It is not possible with the Java module system to provide classes for one package from two different .jar files. |
Good question. Module system is not considered yet in this version of implementation. I have another version that dumps transformed classes as classdata files at pre-run time, then loads them at image build time to substitute the original ones. I think that will solve the module system problem. But I encountered some other issues with that solution, so turned to current easier solution. I'll see how to make it work with module system. ---- Updated 2024/1/5----- |
93de0f3
to
4daafb3
Compare
Has there been any progress toward adding support for Java agents? |
Would the final solution support transforming JDK built-in classes, such as |
There will be a major update of this PR very soon. I have been working on issues that are exposed when we apply this PR with Opentelemetry agent. |
This issue will be addressed in the upcoming update of this PR. But it does not automatically apply your transformed JDK classes into native image, because GraalVM itself depends on those classes as well. You need to write static transformation class with APIs provided by this PR. The details will be published soon. |
4daafb3
to
7b089dd
Compare
fa5a133
to
02b620c
Compare
02b620c
to
46edf40
Compare
@ziyilin I have opened an internal PR to merge, but to run the tests we first need to resolve conflicts. |
This commit supports the static class instrumentation by agent, i.e. the target class is transformed in Agent's preMain method. Instrumentation is supported in 3 stages: 1. Interception stage: native-image-agent records all the transfromed classes, dynamic generated classes, and the target agent's premain method. 2. Build time stage: Instrumented classes are prepended to the beginning of imageCp or patched to modules, so they will override their original classes at build time. 3. Runtime stage: Add premain in JavaMainWrapper before executing Java main. The recorded agent premain method shall be executed at this moment. It is the agent developer's responsibility to make sure the premain is compatible with native image. For example, the byte code transformation should be removed from the native premain.
a5df22a
to
d680a61
Compare
Hi Folks, any news on that topic? I was hoping for that since a while. |
This PR supports Java agent instrumentation in native image.
Scope
Java agent can instrument and transform runtime Java classes in two ways:
This PR only supports the first kind of Java agent instrumentation, i.e. the premain way.
General Idea
The general idea of this PR is to compile the recorded transformed class into native image.
It is implemented in three stages:
instrument-config.json
file and the transformed classes are dumped toinstrument-classes
directory. The classes are organized in the form ofmodule/package/class
.premain
execution inJavaMainWrapper
before executing the main method. The recorded agent premain method shall be executed at this moment.Why don't instrument the classes at build time by starting
native-image
along with agent?GraalVM is a Java application. Instrumenting at build time will change the behaviors of GraalVM itself, especially when the JDK classes are enhanced by the agent.
Agent Developers' Work
Due to the complexity of agent instrumentation, this PR cannot automatically do all the work. It relies on the agent developer to provide the following input:
premain
method implementation. This PR supports runningpremain
method in native image to initiate the instrumentation. But the agent developer should make sure the code running in native image works well. For example, apremain
method can do two things, 1) turn a global flag on, which activates all the instrumented code; and 2) do bytecode transformation. In native image only the first task should be executed, the second task is not necessary and cannot be executed.I have prepared an adaption project for OpenTelemetry Java agent 1.32.0 at https://github.com/aliyun/alibabacloud-microservice-demo/tree/master/graalvm-native-image-demo/opentelemetry-agent-native. It has been tested with the Spring boot demo and works well.
Enhance JDK classes
This PR introduces new annotations (see Advice and Aspect for details) to modify methods with advice, i.e. actions taken before and after original method invocation. They follow idioms of byte-buddy Advice which is widely used in OpenTelemetry java agent. The agent developers can easily write JDK class enhancements that take effects in native image only without interfering with GraalVM at build time. The following actions are supported:
This PR automatically generates substitution classes from classes with Aspect and Advice annotations and registers them before static analysis. If user defined JDK class enhancement conflicts with the one defined by GraalVM, i.e. two substitution methods are mapped to the same original method, the user defined one will be ignored.
Simple Demo
Here is a simple demo project.
agent-demo.zip
The following steps can show how this PR works:
Build this PR and assume the result is placed at
$GRAALVM_HOME
.Unzip the file.
Run
mvn package
to build the demo project.Run
java -cp application/target/application-1.0-SNAPSHOT.jar org.example.Main
. The result should beThis is foo
This is bar
0
Run
collectInstrument.sh
to collect instrumentation configurations. Now the program is instrumented, the output should bebefore foo
This is foo
before foo
This is bar
2
Run
build.sh
to build the demo native image.Run the built native image. The result should be the same as step 6.
Opentelemetry Demo
This PR can now work with OpenTelemetry agent. This demo project shows how to run the Spring boot project with OT agent in native image.
One thing should be noted is in run.sh I use
-agentpath:
for native-image-agent but not-agentlib
, because the latter runs into a crash. In theory, these two options should be the same. I have reported it as a GraalVM JDK issue. More details can be found here (#8094).Limitation
As native image has only one classloader at runtime, any function relies on multiple classloaders may not work as expected.