API Updates: 8191116: [Nestmates] Update core reflection, MethodHandle and varhandle APIs to allow for nestmate access

David Holmes david.holmes at oracle.com
Fri Feb 16 09:20:18 UTC 2018


Hi Karen,

On 16/02/2018 8:01 AM, Karen Kinnear wrote:
> David,
> 
> I think that is a much better solution. Let the description of each 
> Lookup mode be precise, and you have already updated PRIVATE mode to
> include nestmates.

Okay I've deleted that sentence.

Unfortunately something has broken specdiff so I can't regenerate the 
docs at the moment - and I've lost the ones I had generated.

> 
> I brought this concern up in the EG meeting  yesterday and wanted to 
> clarify the difference
> between handling of inner/outer classes for backward compatibility and 
> general nestmate handling.

Many thanks for that detailed walk through.

David
-----


> Assumptions:
> 1. MethodHandle/VarHandle behavior is modeled on bytecode behavior.
> 2. Nestmates have the added capability of access to private members of 
> their nestmates. Period.
> 3. In future we expect to use nestmates for more than inner/outer classes.
> 4. Inner/outer classes will continue to have the InnerClasses attribute, 
> and starting in JDK11, javac
> will also generate NestHost and NestMember attributes.
> 5. With Nestmates, javac will not generate the default (package) 
> trampolines to allow inner/outer
> classes to access each other’s private members. Note that today this is 
> only done for members that
> have compile time accesses.
> (6. With Nestmates, bridges for protected members will still be 
> generated unchanged.)
> 
> For nestmates in general, the modifications you have made below allow a 
> nestmate to access private
> members of their nestmates to match the bytecode behavior.
> 
> Prior to nestmates, there is a special workaround in 
> MethodHandles.Lookup.in() to allow inner/outer
> classes to access any member of any class that shares its top level 
> class to emulate the generated trampolines.
> 
> https://docs.oracle.com/javase/9/docs/api/java/lang/invoke/MethodHandles.Lookup.html#lookupModes--
> 
> In some cases, access between nested classes is obtained by the Java 
> compiler by creating an wrapper method to access a private method of 
> another class in the same top-level declaration. For example, a nested 
> class |C.D| can access private members within other related classes such 
> as |C|, |C.D.E|, or |C.B|, but the Java compiler may need to generate 
> wrapper methods in those related classes. In such cases, a 
> |Lookup| object on |C.E| would be unable to those private members. A 
> workaround for this limitation is the |Lookup.in| 
> <https://docs.oracle.com/javase/9/docs/api/java/lang/invoke/MethodHandles.Lookup.html#in-java.lang.Class-> method, 
> which can transform a lookup on |C.E| into one on any of those other 
> classes, without special elevation of privilege.
> 
> This workaround will continue to be supported going forward explicitly 
> for inner/outer classes.
> A side-effect of this workaround is the ability of the returned Lookup 
> to access not only private methods in
> the “related” class, but also protected and inherited members of that 
> class which are defined in other packages.
> So this workaround will continue to work for inner/outer classes that 
> are also nestmates for backward
> compatibility.
> 
> Going forward, for nestmates in general, the goal is to provide access 
> to private members, which
> can be done via the access check to match bytecode behavior, and does 
> not require special Lookup.in() workarounds.
> 
> If at some point in the future we decide we want increased access for 
> nestmates, we can widen
> this. Let’s just say that the complexity there is challenging and that 
> it is better to err on the side of
> starting out more restrictive.
> 
> Summary - I agree with David. We can leave the documentation as is, with 
> the explicit changes to
> access checking modified below for private members accessible to nestmates.
> 
> thanks David!
> Karen
> 
>> On Feb 14, 2018, at 8:36 PM, David Holmes <david.holmes at oracle.com 
>> <mailto:david.holmes at oracle.com>> wrote:
>>
>> Hi Karen,
>>
>> Thanks for looking at this.
>>
>> On 15/02/2018 1:16 AM, Karen Kinnear wrote:
>>> David,
>>> Re-reading these I had one suggestion:
>>>> - java/lang/invoke/MethodHandles.java
>>>>       * <p>
>>>> -     * In some cases, access between nested classes is obtained by 
>>>> the Java compiler by creating
>>>> -     * an wrapper method to access a private method of another class
>>>> -     * in the same top-level declaration.
>>>> +     * Since JDK 11 the relationship between nested types can be 
>>>> expressed directly through the
>>>> +     * {@code NestHost} and {@code NestMembers} attributes.
>>>> +     * (See the Java Virtual Machine Specification, sections 4.7.28 
>>>> and 4.7.29.)
>>>> +     * In that case, the lookup class has direct access to private 
>>>> members of all its nestmates, and
>>>> +     * that is true of the associated {@code Lookup} object as well.
>>>> +     * Otherwise, access between nested classes is obtained by the 
>>>> Java compiler creating
>>>> +     * a wrapper method to access a private method of another class 
>>>> in the same nest.
>>>>       * For example, a nested class {@code C.D}
>>>>
>>>> Updated the nested classes description to cover legacy approach and 
>>>> new nestmate approach.
>>>>
>>>> -     * {@code C.E} would be unable to those private members.
>>>> +     * {@code C.E} would be unable to access those private members.
>>>>
>>>> Fixed typo: "access" was missing.
>>>>
>>>>       * <em>Discussion of private access:</em>
>>>>       * We say that a lookup has <em>private access</em>
>>>>       * if its {@linkplain #lookupModes lookup modes}
>>>> -     * include the possibility of accessing {@code private} members.
>>>> +     * include the possibility of accessing {@code private} members
>>>> +     * (which includes the private members of nestmates).
>>>>       * As documented in the relevant methods elsewhere,
>>>>       * only lookups with private access possess the following 
>>>> capabilities:
>>>>       * <ul style="font-size:smaller;">
>>>> -     * <li>access private fields, methods, and constructors of the 
>>>> lookup class
>>>> +     * <li>access private fields, methods, and constructors of the 
>>>> lookup class and its nestmates
>>>>
>>>> Clarify that private access includes nestmate access.
>>>>
>>>> -     *  access all members of the caller's class, all public types 
>>>> in the caller's module,
>>>> +     *  access all members of the caller's class and nestmates, all 
>>>> public types in the caller's module,
>>> For the above, I would change this to
>>> * access all members of the caller’s class, all private members of 
>>> nestmates, all types in the caller’s package, all public …
>>> Specifically, we are extended the PRIVATE mode as above to include 
>>> access to all private members of nestmates
>>> and this description is trying to summarize access when all possible 
>>> bits are set.
>>> None of the settings give you access to default (package-private) 
>>> members that a nestmate inherits from a
>>> different package - since the Lookup model is based on the 
>>> JVMS/bytecode behavior.
>>
>> True - you don't get access to a nestmates inherited protected members 
>> declared in a different package. I certainly didn't intend to somehow 
>> imply that.
>>
>>> I added the types in the caller’s package since PACKAGE gives you 
>>> that but it was missing from the existing list.
>>
>> Backing up ... in 8 this method doc simply said:
>>
>> "A freshly-created lookup object on the caller's class has all 
>> possible bits set, since the caller class can access all its own members."
>>
>> It doesn't try to say what a class can access, it just makes the 
>> obvious statement that it can access all its own members. If that was 
>> the current text I would not have needed to make any adjustment for 
>> nestmates.
>>
>> But for 9/10 it states:
>>
>> "A freshly-created lookup object on the caller's class has all 
>> possible bits set, except UNCONDITIONAL. The lookup can be used to 
>> access all members of the caller's class, all public types in the 
>> caller's module, and all public types in packages exported by other 
>> modules to the caller's module."
>>
>> This is quite a different formulation as it now tries to enumerate the 
>> set of accessible things - or at least gives that impression to me! 
>> But it is not complete as it doesn't mention non-public types in the 
>> current package, nor does it mention package-accessible members of 
>> types (whether public or not).
>>
>> With nestmates we have only expanded to include private member access, 
>> but the original text doesn't touch on nestmates directly at all. If 
>> we were to say only "all private members of nestmates" then we seem to 
>> suggest no access to the all the other members (public, directly 
>> declared protected, package). But if we say "nestmates" then that may 
>> imply more than intended as you point out. If we say nothing then we 
>> again imply by omission that there is no nestmate access.
>>
>> This seems to be a bit of an unwravelling thread started by the 
>> changes in 9. I would suggest we simply delete this sentence altogether:
>>
>> "The lookup can be used to access all members of the caller's class, 
>> all public types in the caller's module, and all public types in 
>> packages exported by other modules to the caller's module."
>>
>> as each of the modes, together with the "Access Checking" section of 
>> the class docs, define what is accessible under which mode. I don't 
>> think lookupModes() needs to try and restate that.
>>
>> What do you think?
>>
>> Thanks,
>> David
>>
>>> thanks,
>>> Karen
>>>>
>>>>
>>>> Thanks,
>>>>
>>>> David
> 


More information about the valhalla-spec-observers mailing list