7

Suppose I have a method m:

public void m() {
  String foo = "foo";
  int bar = 0;
  doSomething(foo, bar);
}

I want to use ByteBuddy to instrument the code so that when calling doSomething in m, it will automatically put the value of foo and bar into a HashMap, pretty much something looks like:

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

Is there anyway to do this instrumentation via ByteBuddy?

Rafael Winterhalter
  • 42,759
  • 13
  • 108
  • 192
Gelin Luo
  • 14,035
  • 27
  • 86
  • 139

1 Answers1

3

There is built-in way in Byte Buddy to do redefine method m in this way. Byte Buddy is however voluntarily exposing the ASM API on top of which Byte Buddy is implemented. ASM offers quite extensive documentation which would show you how to do this. I can however tell you that it will be quite a lot of code. Note that you require to compile any method with debug symbols enabled, otherwise these internal variables are not available at run time.

Are you however sure you want to do this? Without knowing your exact use case, it feels like it is a bad idea. By implementing this solution, you make the names of local variables a part of your application instead of letting them be an implementation detail.

I would therefore suggest you to rather instrument the doSomething method. Would this suffice yourn what is easily done in Byte Buddy using an interceptor like the following:

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

This interceptor could then be used as follows:

MethodDelegation.to(new Interceptor()).andThen(SuperMethodCall.INSTANCE);
Rafael Winterhalter
  • 42,759
  • 13
  • 108
  • 192
  • `doSomething` will take any arbitrary arguments: `void doSomething(Object ... args)` So I can't instrument that method. The scenario is to implement a Controller method processor so when user call `render(foo, bar)`, it automatically put the `foo` and `bar` into render argument map which is referenced in the underline template view code – Gelin Luo Jan 11 '15 at 18:43
  • In this case, you will have to use ASM and make sure that you add debug symbols. The smallest entity for interception Byte Buddy knows is a method and I doubt that this is going to change in the future. You may still use Byte Buddy for providing an infrastructure but other than that you need to use ASM. – Rafael Winterhalter Jan 12 '15 at 07:29