简体   繁体   English

无法使用ByteBuddy代理转换类

[英]Cannot transform class with ByteBuddy Agent

I am actually writing a Java agent with ByteBuddy API where I need to monitor some methods. 我实际上是在用ByteBuddy API编写Java代理,需要监视某些方法。 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. TimerInterceptor类似于LoggerInterceptor在ByteBuddy教程中,我曾经找到@SuperCall注解。

The problem is not I am not sure ByteBuddy applied the transformation to the supplied class and method. 问题不是我不确定ByteBuddy是否将转换应用于所提供的类和方法。 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 : 这是我的TimerInterceptor类:

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. 您没有配置Byte Buddy来重新转换已经加载的类。 You can do so by setting .with(RetransformationStrategy.RETRANSFORM) in the agent builder DSL. 您可以通过在代理构建器DSL中设置.with(RetransformationStrategy.RETRANSFORM)来实现。

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. 如果需要更丰富的描述,还可以使用TypePool.Default使Byte Buddy解析类文件而无需加载类。

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. 要查看Byte Buddy在做什么,您可以注册Listener.StreamWriting.toSystemOut() ,在其中将所有发现的类打印到控制台,包括任何潜在的错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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