使用Byte Buddy重新转换类

时间:2016-03-13 09:16:02

标签: java instruments javaagents byte-buddy

Byte Buddy能够加载Instrumentation#retransformClasses吗?我想使用Byte Buddy的Java代理功能,这样我就不必指定-javaagent就可以设置类。例如,使用Javassist就可以实现这一点。但我正在评估用Byte Buddy取代它。

我想在某些方法之前和之后插入静态方法调用。如果可能的话,一个简短的例子会很棒!

1 个答案:

答案 0 :(得分:1)

是的,您可以使用AgentBuilder API启用重新转换。安装代理后,Byte Buddy将重新转换已加载的所有类。您可以启用这样的重新转换:

AgentBuilder builder = new AgentBuilder.Default()    
  .with(RedefinitionStrategy.RETRANSFORMATION)
  .with(InitializationStrategy.NoOp.INSTANCE)
  .with(TypeStrategy.Default.REDEFINE);

您可能想知道需要转换的不同开关:

  1. 您需要启用重新定义(根据检测API重新定义或重新转换)。

  2. 您需要禁用显式初始化策略。否则,Byte Buddy会尝试在任何生成的类中添加显式初始值设定项,以便在加载后将任何值注入类中。这将改变HotSpot VM当前实现不支持的类布局。

  3. 如上所述,检测API的一个限制是您无法添加任何新方法。默认情况下,Byte Buddy将任何截获方法的代码复制到违反此原则的新方法中。通过启用de redefinition类型策略,您可以确保Byte Buddy永远不会重新定义方法。

  4. 或者,您可以选择不使用Byte Buddy的拦截API,它现在完全取代截获的方法,但使用例如最近添加的Advice类进行手动重新定义。

    这样,您可以通过建议自己的代码来增强现有代码,例如Advice.to(Foo.class),在截获方法之前和之后插入引用类的字节代码:

    class Foo {
      @Advice.OnMethodEnter
      @Advice.OnMethodExit
      private static void intercept() {
        System.out.println("Before/after");
      }
    }
    

    您可以在Advice的javadoc中找到更多信息。