首页 > 解决方案 > ByteBuddy 的 Implementation.Composable 和 Implementation.Compound 有什么区别?

问题描述

在 ByteBuddy 中,看似有两种排序方式Implementation

使用一种方式,您可以将它们链接在一起:

// Implementation.Composable; MethodCall "is a" Implementation.Composable; "is a" Implementation
someMethodCall.andThen(someOtherMethodCall)

使用另一个,您可以将它们添加为列表:

// Implementation.Compound; "is a" Implementation
new Implementation.Compound(myListOfImplementations)

在这两种情况下,您最终都会得到一个对象,它本身就是一个Implementation,因此适合提供给intercept方法

他们是否打算以本质上平等的方式做同样的事情?

我问这个问题是因为我碰巧有几个Implementations ( MethodCalls 碰巧),所以在我看来,我可以只使用Implementation.Compound带有 s 列表的构造函数Implementation。但是我也熟悉这个andThen()方法,所以我犹豫了。

无论如何,当我使用Implementation.Compound表单时,如果我将两个MethodCalls 添加到一个新的Implementation.Compound然后使用结果Implementation.Compound作为intercept()调用的参数,我会在类加载时收到一个字节码验证错误,抱怨缺少堆栈帧:

java.lang.VerifyError: 
Expecting a stack map frame
Exception Details:
  Location:
    com/foo/GeneratedSubclassOf$com$foo$AbstractFactory$26753A95.frob(Lcom/foo/TestFrob$Thing;Ljava/util/List;)V @15: aload_1
  Reason:
    Error exists in the bytecode
  Bytecode:
    0000000: 2b2c 03b9 001e 0200 c000 20b8 0024 b12b
    0000010: 2c04 b900 1e02 00c0 0020 b800 27b1     

请注意尾随的四个空格,这向我天真的眼睛暗示,这里可能缺少某些东西。或者也许它是我的代码的其他一些工件,但是当恰好有一个Implementation提供给 newImplementation.Compound时,一切正常。所以我在想,也许该Implementation.Compound构造不适合对Implementations 进行排序(但它的用途什么)?或者可能有一个错误Implementation.Compound(我认为这不太可能)?

当我将(更麻烦的)Implementation.Composable构造与相同Implementation的 sub 一起使用时,一切正常。

我担心我误解了每个构造应该用于什么。

标签: byte-buddy

解决方案


仅连接两个实例Implementation.Compound,而这些实例彼此不认识。如果您复合两个包含以下内容的实现:

return doSomething();

你最终得到非法代码:

return doSomething();
return doSomething();

使用 的andThen步骤Implementation.Composable,第一种方法确保它不返回值但清除它的堆栈。这样,你最终:

doSomething();
return doSomething();

通常,这两个调整后的实现会通过一个 组合在一起Implementation.Compound,但重要的是通知第一个实现并让它创建复合。


推荐阅读