Rafael is right, as usual. I want to elaborate on your question a bit more, though: You are having a bootstrapping problem here:
- The advice needs to be on the bootstrap class path, otherwise it cannot be used with the bootstrap class
URL
.
- The advice needs ByteBuddy because of the annotations. So BB also has to be on the bootstrap class path.
- If you put your sample code into a single class and also use the BB agent library from there, that one also needs to be on the bootstrap class path. I.e. if you want to run this code
import net.bytebuddy.agent.ByteBuddyAgent;
import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.asm.Advice;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URL;
import static net.bytebuddy.matcher.ElementMatchers.*;
class AgentTest {
public static void main(String[] args) throws IOException {
ByteBuddyAgent.install();
new AgentBuilder.Default()
.disableClassFormatChanges()
.ignore(none())
.with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)
.with(AgentBuilder.RedefinitionStrategy.Listener.StreamWriting.toSystemError())
.with(AgentBuilder.Listener.StreamWriting.toSystemError().withTransformationsOnly())
.with(AgentBuilder.InstallationListener.StreamWriting.toSystemError())
.type(is(URL.class).or(is(Foo.class)))
.transform(
new AgentBuilder.Transformer.ForAdvice()
.advice(
isMethod().and(isPublic()).and(named("openConnection")).or(named("myMethod")),
FooAdvice.class.getName()
)
)
.installOnByteBuddyAgent();
new Foo().myMethod();
}
public static class Foo {
public void myMethod() throws IOException {
new URL("https://google.de").openConnection();
}
}
public static class FooAdvice {
@Advice.OnMethodEnter
public static void enter(@Advice.Origin Method method) {
System.out.println("Entering " + method);
}
@Advice.OnMethodExit
public static void exit(@Advice.Origin Method method) {
System.out.println("Exiting " + method);
}
}
}
you need to add something like this on the Java command line:
java -Xbootclasspath/a:/path/to/my-classes;/path/to/byte-buddy-1.10.13.jar;/path/to/byte-buddy-agent-1.10.13.jar ... AgentTest
Then you get this output:
[Byte Buddy] BEFORE_INSTALL net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer@27bc2616 on sun.instrument.InstrumentationImpl@3941a79c
[Byte Buddy] REDEFINE BATCH #0 [2 of 2 type(s)]
[Byte Buddy] TRANSFORM AgentTest$Foo [null, null, loaded=true]
[Byte Buddy] TRANSFORM java.net.URL [null, null, loaded=true]
[Byte Buddy] REDEFINE COMPLETE 1 batch(es) containing 2 types [0 failed batch(es)]
[Byte Buddy] INSTALL net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer@27bc2616 on sun.instrument.InstrumentationImpl@3941a79c
Entering public void AgentTest$Foo.myMethod() throws java.io.IOException
Entering public java.net.URLConnection java.net.URL.openConnection() throws java.io.IOException
Entering public java.net.URLConnection java.net.URL.openConnection() throws java.io.IOException
Exiting public java.net.URLConnection java.net.URL.openConnection() throws java.io.IOException
Entering public java.net.URLConnection java.net.URL.openConnection() throws java.io.IOException
Entering public java.net.URLConnection java.net.URL.openConnection() throws java.io.IOException
Exiting public java.net.URLConnection java.net.URL.openConnection() throws java.io.IOException
Exiting public java.net.URLConnection java.net.URL.openConnection() throws java.io.IOException
Exiting public java.net.URLConnection java.net.URL.openConnection() throws java.io.IOException
Exiting public void AgentTest$Foo.myMethod() throws java.io.IOException
As an alternative, you can use a spring-board Java agent which dynamically puts BB and your transformer onto the bootstrap class path without directly referring to any of their classes. You can subsequently kick off transformation via reflection.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…