Customizable advice dispatcher
See original GitHub issueAFAIK, there are currently two ways advices are dispatched.
By default, advice methods are inlined in to the instrumented method.
public class InlinedAdvice {
@Advice.OnMethodEnter
public static void onFoo(@Advice.Argument(0) boolean bar) {
System.out.println("foo: " + bar);
}
}
public class InstrumentedClass {
public void foo(boolean bar) {
System.out.println("foo: " + bar);
}
}
If the inline
property is set to false
, only a static method call is inserted into the instrumented method that calls the advice method.
public class DelegatedAdvice {
@Advice.OnMethodEnter(inline = false)
public static void onFoo(@Advice.Argument(0) boolean bar) {
System.out.println("foo: " + bar);
}
}
public class InstrumentedClass {
public void foo(boolean bar) {
InlinedAdvice.onFoo(bar);
}
}
I’d like to have a way to customize the dispatching.
public class CustomDelegationAdvice {
@Advice.OnMethodEnter(inline = false)
@Advice.Dispatcher(CustomDispatcher.class)
public static void onFoo(@Advice.Argument(0) boolean bar) {
System.out.println("foo: " + bar);
}
}
public class InstrumentedClass {
public void foo(boolean bar) {
MethodHandleDispatcher
.getMethodHandle(getClass().getClassLoader(), "CustomDelegationAdvice#onFoo")
.invoke(bar);
}
}
MethodHandleDispatcher
is a registry where I would make sure to add method handles to all advice methods. Currently, I do that style of dispatching manually by creating an inlined advice that contains the MethodHandle
lookup and invocation. It would be great if I could just write the advice as it was a inline = true
advice and if Byte Buddy could inject the method handle lookup and invocation in a similar way that it currently does for non-inlined advices via net.bytebuddy.asm.Advice.Dispatcher.Delegating
.
This is in the context of this PR: https://github.com/elastic/apm-agent-java/pull/1090
Is that something that would be possible?
Issue Analytics
- State:
- Created 3 years ago
- Reactions:3
- Comments:16 (16 by maintainers)
I’ll look into the possibility of adding additional semantics to a method return value.
As for returning null: the bootstrap mechanism does not support this. You can however bind a constant call site that drops all arguments and returns null, a primitive 0 or nothing depending on the advice methods return type. Have a look at the lookup API for creating such a constant handle.
Any constructor of an instance of CallSite can be used as a bootstrap method. You could for example subclass constant call site for doing so.
And yes, the bootstrap method needs to be visible (and exported) . Otherwise you could breach into protected code using invokedynamic.