Class用Bytebuddy Agent重新改造

Class Retransformation with Bytebuddy Agent

我正在用 ByteBuddy API 编写一个 Java 代理。因此,我想接触已经使用 Bytebuddy DSL 的重新转换功能加载的 类 的方法委托。当我使用 -javaagent 参数启动应用程序时,一切正常并且控制台输出发生了变化,但是在运行时附加 java 代理时,执行了 agentmain 方法,但控制台输出没有发生变化。也许我缺少一些进一步的 ByteBuddy 配置。任何帮助将不胜感激!

这是代理代码:

public class AgentMain {
  private static final String CLASS = "testing.Test";
  private static final String METHOD = "doSomething";

  public static void premain(String agentArgs, Instrumentation instrumentation) {
    System.out.println("premain...");
    new AgentBuilder.Default()
      .with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)
      .type(ElementMatchers.named(INSTRUMENTED_CLASS))
      .transform(new AgentBuilder.Transformer() {
        @Override
        public DynamicType.Builder transform(
          DynamicType.Builder builder,
          TypeDescription typeDescription,
          ClassLoader classLoader,
          JavaModule javaModule
        )
        {
          return builder.method(named(INTERCEPTED_METHOD))
            .intercept(MethodDelegation.to(Interceptor.class));
        }
      }).installOn(instrumentation);
  }

  public static void agentmain(String agentArgs, Instrumentation instrumentation) {
    System.out.println("Running agentmain...");
    new AgentBuilder.Default()
      .with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)
      .type(ElementMatchers.named(INSTRUMENTED_CLASS))
      .transform(new AgentBuilder.Transformer() {
        @Override
        public DynamicType.Builder transform(
          DynamicType.Builder builder,
          TypeDescription typeDescription,
          ClassLoader classLoader,
          JavaModule javaModule
        )
        {
          return builder.method(named(INTERCEPTED_METHOD))
            .intercept(MethodDelegation.to(Interceptor.class));
        }
      }).installOn(instrumentation);
  }
}
public class Interceptor {
  public static void doSomething(String string) throws Exception {
    System.out.println("Intercepted! ");
  }
}

这是应用程序代码:

public class Main {
  public static void main(String args[]) throws Exception {
    while (true) {
      Thread.sleep(1000);
      String say = "Not intercepted!";
      Test test = new Test();
      test.doSomething(say);
    }
  }
}

这是附加代理的代码:

public class Attacher {
  public static void attach(String jarFile, String pid) {
    try {
      ByteBuddyAgent.attach(new File(jarFile), pid);
    }
    catch (Exception e) {
      e.printStackTrace();
    }
  }
}

您可能需要添加 .disableClassFormatChanges(),因为大多数 JVM 不支持在重新转换时更改 classes 的形状。

另外,考虑注册一个AgentBuilder.Listener,看看为什么class不能转换。检测 API 会抑制所有其他错误。

一般情况下,再转化时,Advice API更适合转化。它支持委托的大部分功能 API 但工作方式略有不同。