Java 8 access private member with lambda?

前端 未结 1 1838
一个人的身影
一个人的身影 2021-02-14 08:22

Invoke private method with java.lang.invoke.MethodHandle gives an answer to private member access, while Java access bean methods with LambdaMetafactory gives an answer to lambd

1条回答
  •  感动是毒
    2021-02-14 09:00

    The critical part is the Lookup object that is passed to the LambdaMetafactory on which then revealDirect is invoked.

    From the documententation:

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

    As a consequence, lambda expression can only access methods accessible by the class containing the lambda expression as the JVM provided Lookup object will reflect exactly these access permissions.

    This also works for Java Beans methods as these are public by convention.


    So if you want to invoke private methods you have three options:

    • Generate the lambda instance from within the declaring class of the private method which has access to it. When this class calls MethodHandles.lookup() it will get an appropriate Lookup instance

      A class may also create such a Lookup instance with the desired capabilities and hand it over to another (trusted) class which may use it to perform such reflective operations. This is exactly what happens implicitly when an invokedynamic instruction is executed. A class containing invokedynamic instructions pointing to a bootstrap method within LambdaMetaFactory implies such trust.

      So using all-ordinary operations, its always the class having the access permissions which has to enable the access for another class

    • Starting with Java 9, use MethodHandles.privateLookupIn(Class, MethodHandles.Lookup) to acquire a method handle with private access rights on the specified target class. This is checked against the module access rules. For access within the same module, this should always succeed.
    • Use even more black magic to get hands on an appropriate Lookup instance. The question you have linked mentions the non-public Lookup.IMPL_LOOKUP. If you get hands on this instance and call in(declaringClass) on it, you get an instance with the desired properties. Alternatively you can create a restricted lookup object via MethodHandles.publicLookup() .in(declaringClass) and overwrite its access modifiers (the ones reported by lookupModes() to enable full access. Obviously, both require access override on fields that are not part of the public Java API.

    0 讨论(0)
提交回复
热议问题