簡體   English   中英

如何在 ByteBuddy 中安裝和使用常量 MethodHandle?

[英]How do I install and use a constant MethodHandle in ByteBuddy?

我正在玩ByteBuddy 對常量MethodHandle s 的支持

我試圖(有效地)在一個MethodHandle上查找 MethodHandle,然后從 ByteBuddy 生成的子類中使用它。

(我知道我可以使用 static MethodHandle字段和類型初始值設定項來執行此操作,但我想嘗試使用此常量支持。)

我有一個FieldDescription.Token代表第一個 class 中的一個字段,還有一個TypeDescription代表第一個 class。從這些我可以得到一個FieldDescription.InDefinedShape像這樣: new FieldDescription.Latent(typeDescription, fieldDescriptionToken) 那里我可以獲得這樣的JavaConstant.MethodHandleJavaConstant.MethodHandle.ofSetter(fieldDescriptionLatent) 這很好用。

然后我這樣做:

// Call invokeExact() on the MethodHandle I looked up, but
// call it on that MethodHandle as a constant pool entry.
builder
  .intercept(MethodCall.invoke(INVOKE_EXACT)
             .on(new JavaConstantValue(javaConstantMethodHandle),
                 MethodHandle.class)
             // etc.

通過這樣做,我使用了帶有 StackManipulation 的on重載StackManipulation在這種情況下,它是包裝JavaConstant JavaConstantValue它是JavaConstant.MethodHandle的超類。 如您所見,我正在嘗試在此MethodHandle上調用invokeExact() ,希望將MethodHandle存儲為常量。

我的第一個問題是:這是正確的食譜嗎?

接下來,我將使用這個“字段設置器” MethodHandle在超類中設置的(愚蠢的)字段被命名為fortyTwo並且類型為Integer 您可能會猜到我想將其值設置為什么。 這一切都很好,顯然(還)與 ByteBuddy 沒有任何關系,但它會。

一切都很好。

當我運行我的代碼時,在我有機會做任何事情之前,即在 class 加載期間,我得到了 ByteBuddy 生成的生成子類的ClassFormatError 該錯誤抱怨此子類試圖定義一個具有無效簽名的字段 (:):

java.lang.ClassFormatError: Field "fortyTwo" in class com/foo/bar/GeneratedSubclassOf$com$foo$bar$Baz$26753A95 has illegal signature "V"

我沒有定義這樣的字段。 超類當然可以(見上文),並且如前所述,它的類型是java.lang.Integer 該字段的訪問級別無關緊要。

我查看了DynamicType.Unloaded包含的TypeDescription (顯然是在加載之前)並且沒有fieldTokens ,即 ByteBuddy 確實沒有嘗試在子類中實際定義一個字段。 看來我正在使用的食譜中的某些東西讓它看起來……呃,驗證者? 我猜? 真的不知道嗎? 由常量表示的MethodHandle試圖操縱子類上的字段,當然不存在這樣的字段(我猜測“ V ”是void的字節碼簽名,可能是默認值)。

所以我的最后一個問題是:在這種情況下,為什么使用字段設置MethodHandle常量會讓人覺得ByteBuddy 試圖在子類中定義一個字段? 就好像在定義或存儲常量時字段的所屬類型被刪除了一樣。

我認為這一切都與 ByteBuddy 支持常量MethodHandle的方式有關。 難道是MethodHandle 或者這是MethodHandle本身的某種固有問題(可能只是字段設置)?

我確實注意到在有問題的 ByteBuddy 代碼中有一個(間接地)對void的引用 這對我來說有一定的意義:如果您要合成一個設置字段的方法句柄,那么它的返回類型將為void 我想知道(天真地)這是否真的是傳遞給這里的正確類型,或者這是否可能接近問題所在。

另一方面,似乎為了解析方法句柄常量(在這種情況下)是“字段設置器”,或1 到 4 種方法句柄,包括在內解析必須根據 JVM 的規則進行場分辨率 這些規則(對於這個天真的讀者來說)似乎表明所使用的描述符應該是字段的描述符 認為,ByteBuddy 正在使用合成方法句柄的描述符,在本例中為V (或void )。 我天真的閱讀讓我認為至少在“字段設置器”的情況下, getDescriptor()的返回值應該是getParameterTypes()的返回值中存在的唯一參數的類型。

如果我誤診了這一點,我深表歉意; 我還在學習。

對於后代:事實證明這是 ByteBuddy中的一個錯誤,我已經為此提交了 PR

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM