Invoke private method with java.lang.invoke.MethodHandle给出了私有成员访问的答案,而Java access bean methods with LambdaMetafactory给出了基于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呼叫网站构建器的一部分。如何自定义构建器以控制其访问检查?
的示例答案 0 :(得分:9)
关键部分是传递给Lookup
的{{1}}对象,然后调用LambdaMetafactory
。
执行安全性和访问检查以确保此查找对象能够再现目标方法句柄。这意味着如果target是直接方法句柄但是由不相关的查找对象创建,则破解可能会失败。
因此,lambda表达式只能访问包含lambda表达式的类可访问的方法,因为所提供的JVM revealDirect
对象将完全反映这些访问权限。
这也适用于Java Beans方法,因为它们按惯例为Lookup
。
因此,如果您想调用public
方法,您有三种选择:
从private
方法的声明类中生成lambda实例,该方法可以访问它。当此类调用MethodHandles.lookup()
时,它将获得适当的private
实例
类也可以创建具有所需功能的Lookup
实例,并将其移交给另一个(可信)类,该类可以使用它来执行此类反射操作。这正是执行Lookup
指令时隐式发生的情况。包含指向invokedynamic
内的引导方法的invokedynamic
指令的类意味着这种信任。
因此,使用所有普通操作,它始终是具有访问权限的类,必须启用对另一个类的访问
MethodHandles.privateLookupIn(Class, MethodHandles.Lookup)
获取具有指定目标类的私有访问权限的方法句柄。这是根据模块访问规则进行检查的。要在同一模块中进行访问,这应该始终成功。LambdaMetaFactory
实例。您关联的问题提及非Lookup
public
。如果您开始使用此实例并在其上调用in(declaringClass)
,则会获得具有所需属性的实例。或者,您可以通过MethodHandles.publicLookup()
Lookup.IMPL_LOOKUP
创建受限制的查找对象,并覆盖其访问修饰符(lookupModes()
报告的访问修饰符以启用完全访问权限。显然,两者都需要对非字段的访问覆盖.in(declaringClass)
Java API的一部分。