I'm creating an agent and using bytebuddy. I'd like to measure the time it takes to execute the java.net.http.HttpClient
's send
method.
// premain
public static void premain(String arguments, Instrumentation instrumentation) {
new AgentBuilder.Default()
.ignore(ElementMatchers.none())
.with(Listener.StreamWriting.toSystemOut().withErrorsOnly())
.type(hasSuperType(named("java.net.http.HttpClient")))
.transform((builder, typeDescription, classLoader,
module, protectionDomain) -> {
return builder
.visit(Advice.to(SendAdvice.class)
.on(hasMethodName("send")
.and(returns(named("java.net.http.HttpResponse")))));
})
.asTerminalTransformation()
.installOn(instrumentation);
}
// Transport
public class Transport {
public static void send() {
System.out.println("hello static");
}
}
// Advice
class SendAdvice {
@Advice.OnMethodEnter()
public static long start() {
return System.nanoTime();
}
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
public static void exit(
@Advice.Enter long startTime) throws MalformedURLException {
Transport.send(System.nanoTime() - startTime);
}
}
For some reason, the Transport.send
is not being invoked. I only have a logging statement in there but it doesn't log. If i just inline the log statement in the exit
method, it works.
The Transport
class is invoked from the HTTP agent, which is part of the JDK and on the platform class loader. The platform class loader cannot see your agent which lives on the system loader.
You would need to inject your "general infrastructure" into the boot loader via the Instrumentation
instance that is presented to your agent. Byte Buddy offers convenience for this by the ClassInjector
hierarchy.