无法使用ByteBuddy代理转换类

时间:2019-08-21 09:51:47

标签: java byte-buddy javaagents

我实际上正在用ByteBuddy API编写Java代理,我需要监视一些方法。举例来说,我需要记录一个方法的执行时间。

这是我的代码:

    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);
  }

}

TimerInterceptor与ByteBuddy教程中的LoggerInterceptor类似,我在其中使用了@SuperCall批注。

问题不是我不确定ByteBuddy是否将转换应用于所提供的类和方法。我可以看到该代理程序正在我的应用程序中加载,但是当我执行监视方法时,什么也没有发生。

这是我的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;
    }
}

任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:0)

您没有配置Byte Buddy来重新转换已经加载的类。您可以通过在代理构建器DSL中设置.with(RetransformationStrategy.RETRANSFORM)来实现。

如果可以避免重新转换,即,如果您仅检测执行代理程序时未加载的应用程序类,则可以跳过此步骤。而是,使用基于字符串的匹配器,并且不要加载该类。如果需要更丰富的描述,还可以使用TypePool.Default来使Byte Buddy解析类文件而无需加载类。

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