[英]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的示例
關鍵部分是傳遞給LambdaMetafactory
的Lookup
對象,然后調用revealDirect
。
從文件記錄 :
執行安全性和訪問檢查以確保該查找對象能夠再現目標方法句柄。 這意味着如果target是直接方法句柄但是由不相關的查找對象創建,則破解可能會失敗。
因此,lambda表達式只能訪問包含lambda表達式的類可訪問的方法,因為JVM提供的Lookup
對象將准確反映這些訪問權限。
這也適用於Java Beans方法,因為它們是按慣例public
的。
因此,如果要調用private
方法,則有三個選項:
從可以訪問它的private
方法的聲明類中生成lambda實例。 當這個類調用MethodHandles.lookup()
,它將獲得一個合適的Lookup
實例
類也可以創建具有所需功能的Lookup
實例,並將其交給另一個(可信)類,該類可以使用它來執行這樣的反射操作。 這正是執行invokedynamic
指令時隱式發生的情況。 包含指向LambdaMetaFactory
的引導方法的invokedynamic
指令的類意味着這種信任。
因此,使用所有普通操作,它始終是具有訪問權限的類,必須啟用對另一個類的訪問
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.