5

I have an Implementation resulting from the return value of Advice#wrap(Implementation), and a FixedValue. I need to turn these into a single Implementation that does not result in a bytecode verification error.

That is:

Implementation advisedMethodCall = Advice.to(...).wrap(someMethodCall);
Implementation firstArgument = FixedValue.argument(0);
// How can I "run" advisedMethodCall followed by firstArgument?

More generally: how do I take two Implementations (that are not instances of Implementation.Composable) and compose them?

(I know from prior experiments that MethodCall achieves this with some sort of inner class named TerminationHandler, where the particular implementation in question, TerminationHandler.Simple.DROPPING, does something to the stack to allow you to compose MethodCalls. I don't know how to do something analogous with an Implementation that is not a MethodCall (e.g. one resulting from Advice#wrap(Implementation)).)

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
Laird Nelson
  • 15,321
  • 19
  • 73
  • 127
  • Laird, sorry to abuse this comment in order to ask a semi personal, semi professional question: You are the guy here on SO who regularly asks the most sophisticated Byte Buddy questions. This is intriguing. What exactly are you doing with BB? Feel free to contact me via any of the channels listed in my profile. I can then delete this comment subsequently. – kriegaex Aug 11 '21 at 02:22

1 Answers1

0

I'd suggest:

Advice.to(...).wrap(someMethodCall.andThen(FixedValue.argument(0))

In case that your advice needs to see the original method return value, you can always wrap Advice.to(...).wrap(someMethodCall) with another advice where you change the returned value.

Implementations work a bit different then advice in the sense that they are not meant to alter existing code. They cannot parse byte code of other implementations in contrast to Advice with decorates existing byte code. So you can write an advice that changes the return value as:

Advice.to(ReturnChangeAdvice.class).wrap(Advice.to(...).wrap(someMethodCall))
Rafael Winterhalter
  • 42,759
  • 13
  • 108
  • 192
  • Thanks, Rafael; I should have mentioned that for (current) architectural reasons I have to apply `FixedValue.argument(0)` _after_ the advised method. So I can't just do `Advice.to(...).wrap(methodCall.andThen(...))`. Let's say I have two method calls "inside" a "housing" method. I'm basically trying to wrap each of the two in a `try`/`finally` block in ByteBuddy, then return argument 0 of the housing method. It sounds like `Implementation`s are not arbitrarily composable. – Laird Nelson Aug 11 '21 at 13:54