dimanche 5 septembre 2021

LambdaMetaFactory and Private Methods

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?





Aucun commentaire:

Enregistrer un commentaire