Context
I am implementing byte code transformations with ByteBuddy and the process of manipulation is a multi step process. Because of that, the manipulation has to be able to:
- augment originally existing methods
- create new methods entirely
- augment a method that was introduced via 2.
For 1. I used an @OnMethodExit advice applied via:
Builder<?> builder = builder.visit(Advice.to(Helper.class)
.on(ElementMatchers.hasMethodNamed(name));
with Helper the augmentation code for the method (effectively setting a field's value).
When creating new methods, I build them as follows:
Builder<?> builder = builder.defineMethod(…)
.intercept(MethodDelegation.to(OtherHelper.class));
.…;
OtherHelper consumes the runtime instance via a static method taking @This Object object as argument.
The problem
In short: I don't see the former transformation applied if it follows the latter. The actual execution order is as follows:
- My type gets processed and a method added via
MethodDelegation.…. - In a subsequent step I find that newly introduced method and try to augment the implementation generation through
Advice.to(…)using an@OnMethodExitadvice. - The resulting code has the behavior of step 1 but is lacking the behavior of step 2.
I am assuming I invalidly combine the two parts of the implementation. Any ideas? A hunch: does the ElementMatcher matching the augmentation by name not see the method introduced using ….defineMethod(…) yet? The name is coming from some method inspection I start from builder.toTypeDescription() which actually makes me assume that the to-be-created method is already visible to the builder as otherwise it wouldn't be found in that step in the first place.