当前位置: 首页 > 知识库问答 >
问题:

使用Bytebuddy代理重新传输类

弓宏茂
2023-03-14

我正在用bytebuddyapi编写一个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();
    }
  }
}

共有1个答案

关昊天
2023-03-14

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

另外,考虑注册一个代理生成器。侦听器查看类无法转换的原因。否则,instrumentation API将抑制所有错误。

通常,在重新传输时,通知API更适合于转换。它支持委托API的大多数功能,但工作原理略有不同。

 类似资料:
  • 字节伙伴代理是否能够克服附加API限制,例如“新方法定义”、“静态变量更改”?我可以看到,正在从代理生成器调用重定义类方法,但不确定这是否也遵循与附加API相同的限制。 我试图了解我是否可以做到以下几点: 1) 使用应用程序类加载器加载代理jar,例如并行WebAppClassLoader。我的应用程序是一个servlet webapp,在运行时它使用上面的类加载器加载所有应用程序类。 2) 完全

  • 我试图在java上重新定义类。lang包,如String。类或整数。使用ByteBuddy初始化,但没有成功。我的问题是这是否可能? 这是我在我的java代理中尝试的代码: 当我检查日志的输出时,我看到的关于String类的内容是: 这是否意味着ByteBuddy没有重新定义String类?这可能吗? 非常感谢。

  • 无法使用ByteBuddy重新定义java.io.ObjectInputStream。 我已经尝试了很多方法来解决这个问题。但我找不到钩住“java.io.ObjectInputStream$resolveClass”的方法。你能帮助我吗?

  • homebody能帮我提示一下如何使用byte buddy 1.6.9重新定义静态方法吗? 我试过这个: 我遇到以下异常: 线程“main”java.lang.IllegalStateException中的异常:无法注入已经加载的类型:类委托。来源 谢谢

  • 例如,假设有一个接口(StoredOnDatabase)带有一些有用的方法,可以从数据库中读取和写入bean。假设有一些类没有实现这个接口,而是用注释@bean进行了注释。当这个注释出现时,我想: 创建实现StoredonDatabase接口的bean代理; 为setter添加拦截器,当bean的属性被修改时,我可以使用这些拦截器来“跟踪”; 使用对所有这些bean都有效的泛型equals()和h

  • 我正在尝试在项目中检测一些类。当我将代理类打包到jar中并通过-javaagent使用它时,它工作正常。 当我尝试直接在项目中运行它时,检测有时会失败。(我在测试类的静态块中初始化bytepal)。 例如,当我添加这个测试时,我的代码不再被截获。用try/catch做同样的事情是有效的。 有没有一种安全的方法来仪器类在同一个项目没有-javaagent? 项目在OpenJdk11上。