Given Sample.someMethod(...)
and InvocationHandler decoration
, I want to create a dynamic subclass that overrides someMethod
with
someMethod(...) {
decoration.invoke(...);
super.someMethod(...);
}
My code looks like this:
Class<? extends Sample> dynamicSubclass = new ByteBuddy()
.subclass(Sample.class)
.method(ElementMatchers.named("someMethod"))
.intercept(new Implementation.Compound(
InvocationHandlerAdapter.of(decoration),
SuperMethodCall.INSTANCE))
.make()
.load(Sample.class.getClassLoader()) // line 42
.getLoaded();
...and it results in the following exception:
java.lang.VerifyError: Expecting a stack map frame
Exception Details:
Location:
pl/morgwai/sample/pojo/ByteBuddySample$Sample$ByteBuddy$PXUw8Sz7.someMethod(I)Ljava/lang/String; @27: aload_0
Reason:
Error exists in the bytecode
Bytecode:
0000000: b200 0a2a b200 0e04 bd00 1059 031b b800
0000010: 1653 b900 1c04 00c0 001e b02a 1bb7 0020
0000020: b0
at java.base/java.lang.Class.getDeclaredFields0(Native Method)
at java.base/java.lang.Class.privateGetDeclaredFields(Class.java:3061)
at java.base/java.lang.Class.getDeclaredField(Class.java:2409)
at net.bytebuddy.implementation.LoadedTypeInitializer$ForStaticField.onLoad(LoadedTypeInitializer.java:122)
at net.bytebuddy.implementation.LoadedTypeInitializer$Compound.onLoad(LoadedTypeInitializer.java:192)
at net.bytebuddy.dynamic.TypeResolutionStrategy$Passive.initialize(TypeResolutionStrategy.java:102)
at net.bytebuddy.dynamic.DynamicType$Default$Unloaded.load(DynamicType.java:6292)
at net.bytebuddy.dynamic.DynamicType$Default$Unloaded.load(DynamicType.java:6281)
at pl.morgwai.sample.pojo.ByteBuddySample.main(ByteBuddySample.java:42)
What am I doing wrong and how to fix it?
(I'm using byte-buddy 1.10.22 and openjdk-11)
Thanks!
UPDATE:
I'm able to achieve
someMethod(...) {
decoration.invoke(...);
}
and
someMethod(...) {
super.someMethod(...);
}
by doing .intercept(InvocationHandlerAdapter.of(decoration))
and .intercept(SuperMethodCall.INSTANCE)
respectively, so it seems, I'm not using Implementation.Compound
properly...
UPDATE-2:
I'm also able to achieve
someMethod(...) {
super.someMethod(...);
decoration.invoke(...);
}
by
.intercept(SuperMethodCall.INSTANCE.andThen(InvocationHandlerAdapter.of(decoration)))
but I can't do the other way around to achieve the order I need as InvocationHandlerAdapter
does not implement Implementation.Composable
...
As kindly explained by Rafael Winterhalter it's an unintended omission and in the next release InvocationHandlerAdapter
will be implementing Composable
(commit already pushed) and then the simplest way will be to do
.intercept(InvocationHandlerAdapter.of(decoration).andThen(SuperMethodCall.INSTANCE))