【发布时间】:2021-11-03 03:57:20
【问题描述】:
我想使用 LambdaMetaFactory 来有效地访问私有方法。
public class Foo {
private void bar() { // here's what I want to invoke
System.out.println("bar!");
}
}
我知道这不是安全违规,因为以下代码有效:
Foo foo = new Foo();
Method m = Foo.class.getDeclaredMethod("bar");
m.setAccessible(true);
m.invoke(foo); // output: bar!
但是,我尝试使用 LambdaMetaFactory 失败了:
MethodHandles.Lookup lookup = MethodHandles.lookup();
Method m = Foo.class.getDeclaredMethod("bar");
m.setAccessible(true);
CallSite site = LambdaMetafactory.metafactory(lookup, "accept",
MethodType.methodType(Consumer.class),
MethodType.methodType(void.class, Object.class),
lookup.unreflect(m),
MethodType.methodType(void.class, Foo.class));
Consumer<Foo> func = (Consumer<Foo>) site.getTarget().invoke();
func.accept(foo); // IllegalAccessException: member is private
显然m.setAccessible(true) 在这里还不够。我尝试将lookup 更改为MethodHandles.privateLookupIn(Foo.class, MethodHandles.lookup()),确实在我的玩具示例中解决了它......但在我的实际应用程序中却没有,它生成一个IllegalAccessException 说我的班级“没有完全特权访问”。我一直无法发现为什么我的应用程序“没有完全权限访问”,或者如何解决它。
我发现几乎可以工作的唯一一件事是:
MethodHandles.Lookup original = MethodHandles.lookup();
Field internal = MethodHandles.Lookup.class.getDeclaredField("IMPL_LOOKUP");
internal.setAccessible(true);
TRUSTED = (MethodHandles.Lookup) internal.get(original);
这允许我使用TRUSTED 代替lookup,只要我在VM 选项中有--illegal-access=permit,我可以这样做。这会产生一个NoClassDefFoundError(说它找不到Foo),这看起来很有希望......但我仍然无法弄清楚如何让它完全工作,只产生这个错误而不是其他错误.
这里发生了什么,如何通过LambdaMetaFactory 访问bar?
【问题讨论】:
-
“没有完全权限访问”-是的,在某些 Java 版本(iirc Java 14)中已更改,所以我猜您在玩具示例中运行的 Java 版本不同,而您的实际应用。
标签: java reflection java-16 methodhandle lambda-metafactory