javabyte-buddyjavaagents

Bytebuddy: How to inject class that can be read by java.net.http.HttpClient#sendAsync


I'm trying to time time it takes for the CompletableFuture that is being returned by java.net.http.HttpClient#sendAsync

// premain
public static void premain(String arguments, Instrumentation instrumentation) {
    // ...inject helper class to bootloader
    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(SendAsyncAdvice.class)
                  .on(hasMethodName("async")));
        })
        .asTerminalTransformation()
        .installOn(instrumentation);
  }

class SendAsyncAdvice {
  @Advice.OnMethodExit()
  public static void exit(
      @Advice.Return(readOnly = false) CompletableFuture<HttpResponse<?>> future) {
    future = future.whenComplete(new ResponseConsumer());
  }
}

class ReponseConsumer implements BiConsumer<HttpResponse<?>, Throwable> {
  @Override
  public void accept(HttpResponse<?> arg0, Throwable arg1) {
    System.out.println("HELLO");
  }
}

I injected the ReponseConsumer to the bootloader and I'm getting this error

Exception in thread "main" java.lang.IllegalAccessError: 
failed to access class io.hello.agent.SendAsyncAdvice 
from class jdk.internal.net.http.HttpClientImpl
 (io.hello.agent.SendAsyncAdvice is in unnamed module of loader 
'bootstrap'; jdk.internal.net.http.HttpClientImpl 
is in module java.net.http of loader 'platform')

Just wondering how do i make the ReponseConsumer class available in java.net.http module


Solution

  • You are hitting the module system's boundaries and you have to add a read edge from your http client's module to the injected class. You can do so by adding a step in your code: assureReadEdgeTo where you reference the target class or module.