I would like to use LambdaMetaFactory to efficiently access a private method.
public class Foo { private void bar() { // here's what I want to invoke System.out.println("bar!"); }}
I know it is not a security violation, because the following code works:
Foo foo = new Foo();Method m = Foo.class.getDeclaredMethod("bar");m.setAccessible(true);m.invoke(foo); // output: bar!
However, my attempts to use LambdaMetaFactory fail:
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
Clearly m.setAccessible(true)
is not enough here. I tried changing lookup
to MethodHandles.privateLookupIn(Foo.class, MethodHandles.lookup())
, which did solve it in my toy example ... but not in my actual application, where it generates an IllegalAccessException
saying my class "does not have full privilege access". I have been unable to discover why my application "does not have full privilege access", or how to fix it.
The only thing I've found to sort-of-almost work is this:
MethodHandles.Lookup original = MethodHandles.lookup();Field internal = MethodHandles.Lookup.class.getDeclaredField("IMPL_LOOKUP");internal.setAccessible(true);TRUSTED = (MethodHandles.Lookup) internal.get(original);
Which allows me to use TRUSTED
in place of lookup
, as long as I have --illegal-access=permit
in the VM options, which I can do. This produces a NoClassDefFoundError
instead (saying it can't find Foo
), which seems promising ... but I still can't figure out how to get it to work entirely, just produce this error instead of the other ones.
What is happening here, and how can I access bar
through LambdaMetaFactory
?