Java 8 private member access with lambda?

Calling a private method with java.lang.invoke.MethodHandle gives a response to access a private member, and access to a Java bean with LambdaMetafactory gives a response to access to a lambda membership. However, combining the two, I still cannot find a way to access private members via lambda. Error:

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) 

points to revealDirect , which is part of the metafactory site creator. How can I configure the builder to control his access control?

UPDATE : Example Working Solution # 2 for Holger

+5
source share
1 answer

The critical part is the Lookup object, which is passed to LambdaMetafactory , on which revealDirect is revealDirect .

From the docs documentation :

Security and access checks are performed to ensure that this search object is capable of reproducing the target method descriptor. This means that hacking may fail if the target is a direct method descriptor but was created by an unrelated search object.

As a result, a lambda expression can only access methods that are accessible to the class containing the lambda expression, since the JVM object provided by Lookup will accurately reflect these access rights.

This also works for Java Beans, as they are public by convention.


So, if you want to call private methods, you have two options:

  • Create an instance of lambda from the private method declaration class that has access to it. When this class calls MethodHandles.lookup() , it will get the corresponding Lookup instance.

    A class can also create such an instance of Lookup with the required capabilities and pass it to another class (trusted), which can use it to perform such reflexive operations. This is exactly what happens implicitly when the invokedynamic statement is invokedynamic . A class containing invokedynamic instructions pointing to the boot method in LambdaMetafactory implies such trust.

    Thus, using all the usual operations, there is always a class that has access permissions that should allow access to another class

  • Use even more black magic to get the corresponding Lookup instance. The question you mentioned doesn’t mention public Lookup.IMPL_LOOKUP . If you get this instance and call in(declaringClass) , you will get an instance with the required properties. Alternatively, you can create a restricted search object using MethodHandles.publicLookup() .in(declaringClass) and overwrite its access modifiers (those that are reported by lookupModes() to provide full access. Obviously, both require redefinition of access in the fields, which are not part of the public Java API.
+6
source

Source: https://habr.com/ru/post/1212072/


All Articles