使用 ByteBuddy

时间:2021-04-06 11:09:39

标签: java byte-buddy

给定 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)

我做错了什么以及如何解决?
(我使用的是字节伙伴 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...

1 个答案:

答案 0 :(得分:0)

explained by Rafael Winterhalter,这是一个无意的遗漏,在下一个版本中InvocationHandlerAdapter 实施Composablecommit 已经推送)然后最简单的方法是做

.intercept(InvocationHandlerAdapter.of(decoration).andThen(SuperMethodCall.INSTANCE))
相关问题