簡體   English   中英

Java 8訪問lambda的私有成員?

[英]Java 8 access private member with lambda?

使用java.lang.invoke.MethodHandle調用私有方法給出了私有成員訪問的答案,而使用LambdaMetafactory的Java訪問bean方法給出了基於lambda的成員訪問的答案。 但是,通過組合這兩者,我仍然找不到通過lambda訪問私有成員的方法。 錯誤:

Caused by: java.lang.IllegalAccessException: member is private: XXX from ZZZ
at java.lang.invoke.MethodHandles$Lookup.revealDirect(MethodHandles.java:1353)
at java.lang.invoke.AbstractValidatingLambdaMetafactory.<init>(AbstractValidatingLambdaMetafactory.java:131)
at java.lang.invoke.InnerClassLambdaMetafactory.<init>(InnerClassLambdaMetafactory.java:155)
at java.lang.invoke.LambdaMetafactory.metafactory(LambdaMetafactory.java:299)

指向revealDirect ,它是metafactory調用站點構建器的一部分。 如何自定義構建器以控制其訪問檢查?

更新 :每個Holger 工作解決方案選項#3的示例

關鍵部分是傳遞給LambdaMetafactoryLookup對象,然后調用revealDirect

文件記錄

執行安全性和訪問檢查以確保該查找對象能夠再現目標方法句柄。 這意味着如果target是直接方法句柄但是由不相關的查找對象創建,則破解可能會失敗。

因此,lambda表達式只能訪問包含lambda表達式的類可訪問的方法,因為JVM提供的Lookup對象將准確反映這些訪問權限。

這也適用於Java Beans方法,因為它們是按慣例public的。


因此,如果要調用private方法,則有三個選項:

  • 從可以訪問它的private方法的聲明類中生成lambda實例。 當這個類調用MethodHandles.lookup() ,它將獲得一個合適的Lookup實例

    類也可以創建具有所需功能的Lookup實例,並將其交給另一個(可信)類,該類可以使用它來執行這樣的反射操作。 這正是執行invokedynamic指令時隱式發生的情況。 包含指向LambdaMetaFactory的引導方法的invokedynamic指令的類意味着這種信任。

    因此,使用所有普通操作,它始終是具有訪問權限的類,必須啟用對另一個類的訪問

  • 從Java 9開始,使用MethodHandles.privateLookupIn(Class, MethodHandles.Lookup)獲取具有指定目標類的私有訪問權限的方法句柄。 這是根據模塊訪問規則進行檢查的。 對於同一模塊內的訪問,這應該總是成功。
  • 使用更多黑魔法來獲取適當的Lookup實例。 您鏈接的問題提到了非public Lookup.IMPL_LOOKUP 如果您接觸到此實例並在其上調用in(declaringClass) ,則會獲得具有所需屬性的實例。 另外,您可以通過創建一個受限查找對象MethodHandles.publicLookup() .in(declaringClass)和覆蓋其訪問修飾符(報道的那些lookupModes()以實現完全訪問,顯然都需要對不屬於部分領域超越訪問public Java API。

暫無
暫無

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

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