Byte Buddy可以访问方法的局部变量名吗?

Gel*_*Luo 6 java bytecode local-variables byte-buddy

假设我有一个方法m:

public void m() {
  String foo = "foo";
  int bar = 0;
  doSomething(foo, bar);
}
Run Code Online (Sandbox Code Playgroud)

我想用ByteBuddy仪器代码,以便在调用的时候doSomethingm,它会自动把价值foobarHashMap,相当多的东西是这样的:

public void m() {
  String foo = "foo";
  int bar = 0;
  context.put("foo", foo); // new code injected 
  context.put("bar", bar); // new code injected
  doSomething(foo, bar);
}
Run Code Online (Sandbox Code Playgroud)

无论如何通过ByteBuddy做这个仪器?

Raf*_*ter 3

Byte Buddy 中有内置方法可以m通过这种方式重新定义方法。然而,Byte Buddy 自愿公开了 Byte Buddy 所实现的 ASM API。ASM 提供了相当广泛的文档,可以向您展示如何执行此操作。不过我可以告诉你,这将是相当多的代码。请注意,您需要在启用调试符号的情况下编译任何方法,否则这些内部变量在运行时不可用。

但您确定要这样做吗?在不知道您的确切用例的情况下,感觉这是一个坏主意。通过实现此解决方案,您可以使局部变量的名称成为应用程序的一部分,而不是让它们成为实现细节。

因此,我建议您使用该doSomething方法。这足以满足您在 Byte Buddy 中使用如下拦截器轻松完成的操作:

class Interceptor {
  void intercept(@Origin Method method, @AllArguments Object[] args) {
    int index = 0;
    for(Parameter p : method.getParameters()) {
      context.add(p.getName(), args[index++]); 
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

然后可以按如下方式使用该拦截器:

MethodDelegation.to(new Interceptor()).andThen(SuperMethodCall.INSTANCE);
Run Code Online (Sandbox Code Playgroud)