使用 ByteBuddy 向方法添加行为
add behavior to method with ByteBuddy
给定 Sample.someMethod(...)
和 InvocationHandler decoration
,我想创建一个用
覆盖 someMethod
的动态子类
someMethod(...) {
decoration.invoke(...);
super.someMethod(...);
}
我的代码如下所示:
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();
...并导致以下异常:
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)
我做错了什么以及如何解决?
(我使用的是 byte-buddy 1.10.22 和 openjdk-11)
谢谢!
更新:
我能做到
someMethod(...) {
decoration.invoke(...);
}
和
someMethod(...) {
super.someMethod(...);
}
通过分别执行 .intercept(InvocationHandlerAdapter.of(decoration))
和 .intercept(SuperMethodCall.INSTANCE)
,看来,我没有正确使用 Implementation.Compound
...
更新 2:
我也能做到
someMethod(...) {
super.someMethod(...);
decoration.invoke(...);
}
来自
.intercept(SuperMethodCall.INSTANCE.andThen(InvocationHandlerAdapter.of(decoration)))
但我不能用其他方法来实现我需要的顺序,因为 InvocationHandlerAdapter
没有实现 Implementation.Composable
...
请 explained by Rafael Winterhalter it's an unintended omission and in the next release InvocationHandlerAdapter
will be implementing Composable
(commit 已推送)然后最简单的方法就是
.intercept(InvocationHandlerAdapter.of(decoration).andThen(SuperMethodCall.INSTANCE))
给定 Sample.someMethod(...)
和 InvocationHandler decoration
,我想创建一个用
someMethod
的动态子类
someMethod(...) {
decoration.invoke(...);
super.someMethod(...);
}
我的代码如下所示:
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();
...并导致以下异常:
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)
我做错了什么以及如何解决?
(我使用的是 byte-buddy 1.10.22 和 openjdk-11)
谢谢!
更新:
我能做到
someMethod(...) {
decoration.invoke(...);
}
和
someMethod(...) {
super.someMethod(...);
}
通过分别执行 .intercept(InvocationHandlerAdapter.of(decoration))
和 .intercept(SuperMethodCall.INSTANCE)
,看来,我没有正确使用 Implementation.Compound
...
更新 2:
我也能做到
someMethod(...) {
super.someMethod(...);
decoration.invoke(...);
}
来自
.intercept(SuperMethodCall.INSTANCE.andThen(InvocationHandlerAdapter.of(decoration)))
但我不能用其他方法来实现我需要的顺序,因为 InvocationHandlerAdapter
没有实现 Implementation.Composable
...
请 explained by Rafael Winterhalter it's an unintended omission and in the next release InvocationHandlerAdapter
will be implementing Composable
(commit 已推送)然后最简单的方法就是
.intercept(InvocationHandlerAdapter.of(decoration).andThen(SuperMethodCall.INSTANCE))