简体   繁体   中英

Cannot transform class with ByteBuddy Agent

I am actually writing a Java agent with ByteBuddy API where I need to monitor some methods. Let say for instance I need to log the execution time of a method.

Here is my code :

    public class PerfAgents {

     public static void premain(String agentArgs, Instrumentation inst){
        LOGGER.info("[Agent] Loading classes ...");
        Class classToMonitor = getClassFromArgs(agentArgs);
        String methodToMonitor = getMethodFromArgs(agentArgs);
        installAgent(inst, classToMonitor, methodToMonitor);
    }

     private static void installAgent(Instrumentation instrumentation, Class<?> classToMonitor, String methodToMonitor) {
      new AgentBuilder.Default()
           .type(is(classToMonitor))
           .transform((builder, typeDescription, classLoader, module) ->
                {
                    LOGGER.info("Transforming {} for {}", method, classToMonitor.getSimpleName());
                    return builder.method(named(methodToMonitor))
                           .intercept(MethodDelegation.to(TimerInterceptor.class));
           }).installOn(instrumentation);
  }

}

The TimerInterceptor is similar to LoggerInterceptor found in the ByteBuddy tutorial, where I used the @SuperCall annotation.

The problem is not I am not sure ByteBuddy applied the transformation to the supplied class and method. I can see that the agent is loading in my application, but when I execute my method to monitor, nothing happens.

Here is my TimerInterceptor class :

static class TimerInterceptor {

    private static Logger LOGGER = LoggerFactory.getLogger(LogInterceptor.class);


    public static Object log(@SuperCall Callable<Object> callable) throws Exception {
        LocalTime start = LocalTime.now();
        Object called = callable.call();
        LocalTime end = LocalTime.now();
        Duration between = Duration.between(start, end);

        LOGGER.info("Execution time : {} ms", between.toMillis());
        return called;
    }
}

Any help would be appreciated.

You are not configuring Byte Buddy to retransform already loaded classes. You can do so by setting .with(RetransformationStrategy.RETRANSFORM) in the agent builder DSL.

If you can avoid retransformation, ie if you are only instrumenting application classes that are not loaded when the agent is executed, you can however skip this step. Rather, use string-based matchers and do not load the class. If you need a richer description, you can also use a TypePool.Default to let Byte Buddy parse class files without loading classes.

To see what Byte Buddy is doing, you can register a Listener.StreamWriting.toSystemOut() where all discovered classes are printed to the console, including any potential errors.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM