JDK-8177020 : JVMS changes for Nestmates
  • Type: Sub-task
  • Component: specification
  • Sub-Component: vm
  • Affected Version: 10
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2017-03-17
  • Updated: 2022-07-14
  • Resolved: 2017-12-02
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 11
11Fixed
Related Reports
Relates :  
Relates :  
Relates :  
Description
Define all the JVMS changes needed to support nestmates

* Access Control *

Update JVMS 5.4.4:

> A field or method <i>R</i> is accessible to a class or interface
> <i>D</i> if and only if any of the following conditions are true:
> <ul>
>   <li> ... </li>
>   <li> <i>R</i> is private and is declared in a different class or
>   interface <i>C</i>, and <i>C</i> and <i>D</i>, are nestmates. </li>
> </ul>

* Nestmate Definition and Attributes *

Nestmate definition (where to put this?):

TBD

Update 4.7 Attributes

- Now 25 attributes defined
- Update tables and classifications with new attributes

Add: 4.7.25 The `MemberOfNest` Attribute

The `MemberOfNest` attribute is a fixed-length attribute in the `attributes` table of a `ClassFile` structure (§4.1). A class or interface must have a `MemberOfNest` attribute if it represents a class or interface that is not a member of a package (JLS §7.1). Conversely a class or interface that is a member of a package, must not have a `MemberOfNest` attribute.

[note] This implicitly defines that only nested types have a `MemberOfNest` attribute. Conversely, only top-level types, may have a `NestMembers` attribute. Consequently, these two attributes are mutually exclusive - a type can not both be a member of a nest, and itself have nest members.

There may be at most one `MemberOfNest` attribute in the `attributes` table of a `ClassFile` structure.

The `MemberOfNest` attribute has the following format:

MemberOfNest_attribute {
    u2 attribute_name_index;
    u4 attribute_length;
    u2 class_index;
}

The items of the `MemberOfNest_attribute` structure are as follows:

attribute_name_index

The value of the `attribute_name_index` item must be a valid index
into the `constant_pool` table. The `constant_pool` entry at that index
must be a `CONSTANT_Utf8_info` structure (§4.4.7) representing the string "MemberOfNest".

attribute_length

The value of the `attribute_length` item must be two.

class_index

The value of the `class_index` item must be a valid index into the
`constant_pool` table. The `constant_pool` entry at that index must be a
`CONSTANT_Class_info` structure (§4.4.1) representing the top-level class or interface of which the current class or interface claims to be a nest member.


Add: 4.7.26 The `NestMembers` Attribute

The `NestMembers` attribute is a variable-length attribute in the attributes table of a `ClassFile` structure (§4.1).

If the constant pool of a class or interface `C` contains at least one
`CONSTANT_Class_info` entry (§4.4.1) which represents a class or interface that is not a member of a package, then there must be exactly one `NestMembers` attribute in the attributes table of the `ClassFile` structure for `C`. If `C` itself is not a member of a package, then there must not be a `NestMembers` attribute in the attributes table of the `ClassFile` structure for `C`.

The `NestMembers` attribute has the following format:

NestMembers_attribute {
    u2 attribute_name_index;
    u4 attribute_length;
    u2 number_of_classes;
    { u2 nest_member_class_info_index;
    } classes[number_of_classes];
}

The items of the `NestMembers_attribute` structure are as follows:

attribute_name_index

The value of the `attribute_name_index` item must be a valid index
into the `constant_pool` table. The `constant_pool` entry at that index
must be a `CONSTANT_Utf8_info` structure (§4.4.7) representing the string "NestMembers".

attribute_length

The value of the `attribute_length` item indicates the length of the attribute, excluding the initial six bytes.

number_of_classes

The value of the `number_of_classes` item indicates the number of entries in the classes array.

classes[]

Every `CONSTANT_Class_info` entry in the `constant_pool` table which
represents a class or interface `C` that is not a package member must have exactly one corresponding entry in the `classes` array.

Each entry in the `classes` array contains the following item:

nest_member_class_info_index

The value of the `nest_member_class_info_index` item must be a valid index into the `constant_pool` table. The `constant_pool` entry at that index must be a `CONSTANT_Class_info` structure representing `C`.

* Nest Membership validation *

5.4 Linking

Need to document that nest-top is resolved during linking (currently before verification but that may not need to be specified), which can cause class-loading of purported nest-top class and can fail due to normal class-loading exceptions. We also validate that the nest-top agrees the current class is a member of its nest. We identify the following errors for which IncompatibleClassChangeError is thrown (under the assumption that we expect the nest-top to be set correctly at compilation time, so any error must mean at least one of the classes has been changed since then):

- the named nest-top class is not an instance class
- the named nest-top class does not list the current class as a nest member
- the nest-top class and current class are in different packages

NOTE: we do not propose to validate the contents of the nest-members list when a nest-top class is loaded/linked. Such a check would be expensive and would require loading of all nest members at the time.

* Method Resolution *

5.4.3.3

The lookup algorithm in 5.4.3.3 allows for locating the named method anywhere in the class hierarchy, and then applying an accessibility check to prune out a method that should not have been found. In the case of private methods when resolving invokespecial this process can fail if the lookup finds the method higher in the hierarchy but the accessibility check passes due to the classes being nestmates. In the case of invokespecial of a private method the class in which the method is found, must be the static class of the method being resolved. It is unclear whether this extension needs to be documented in 5.4.3.3 or should instead form part of the invokespecial resolution process in 6.5.

* InvokeSpecial Bytecode *

The following changes have been identified:

3.7: "Note that methods called using the invokespecial instruction always pass this to the invoked method as its first argument. As usual, it is received in local variable 0."

With nestmates the first argument need not be this, but may be a nestmate instance. But in fact this statement is already incorrect as the receiver could be another instance of the current class.

4.9.2: "Each invokespecial instruction must name an instance initialization method (§2.9), a method in the current class or interface, a method in a superclass of the current class, a method in a direct superinterface of the current class or interface, or a method in Object.

With nestmates it may also name a method of a nestmate's class.

4.9.2: "If an invokespecial instruction names a method which is not an instance initialization method, then the type of the target reference on the operand stack must be assignment compatible with the current class (JLS §5.2)."

With nestmates the target reference on the operand stack may be that of a nestmate.

We also note that due to 3.7 and 4.9.2 the method to be invoked must be a method of the receiver object. However, with private nestmate access we may also need wording to ensure that the receiver is not only a nestmate instance, but a nestmate of a type that defines the method being invoked.


The following sections may need private nestmate changes, but it is unclear at present:

4.10.1.9 - invokespecial verifier rules

5.4.3.5 Method Type and Method Handle resolution





Comments
I've uploaded another iteration of the spec document that more accurately reflects what will appear in JVMS. All changes are for improved presentation only.
02-05-2018

Just for the record I've gone through the final version and see no issues, and have no further comments. Thanks!
22-01-2018

An update is attached, bringing back a modified version of the `invokeinterface` access check on the selected method. See JDK-8024806.
17-01-2018

A finalized spec proposal is attached.
02-12-2017

An updated draft of JVMS changes is attached.
18-04-2017

My concern with changing invokevirtual to become nestmate aware (and disallow private nestmate access) is that the nestmate check would penalize code that we will allow to proceed. Without knowing how prevalent private invokevirtuals are it will be hard to evaluate the impact. In one-way it adds weight to the migration story "in Java 10 invokevirtual of private methods will continue to be allowed, but may incur a penalty during class resolution; in Java 11 invokevirtual of private methods will no longer be permitted". Of course whatever we do with invokevirtual itself should also be reflected in the the rules applied by MethodHandles. This seems like an extension to the core nestmate work that could be left until later, to ensure no undue strain is placed on the Java 10 release schedule.
27-03-2017

With regard to the specification of link-time versus load-time, I have not yet considered exactly where in the spec this would need to be covered. Without investigating different approaches it would be hard to know if there are distinct points in the overall loading/linking/initialization process between which nest_top resolution and membership validation must occur. Ideally the spec would give as much latitude as possible in that regard.
27-03-2017

So invoke virtual today in the vm supports invoking private methods. When we added private methods to interfaces, we chose to explicitly require using invoke special. Since nest mates are new, this seems like a good opportunity to also require invoke special, since we would like to someday tighten this rule so that methods in classes also require invoke special. So this is a question for the JVMS folks.
24-03-2017

I was inaccurate. We have an implementation choice of resolving the nest_top at load time or link time. You've chosen link time, before verification, and I think that is the right approach to explore. My point was - does this need to be specified in the JVMS? Or are we ok since this is treated as part of constant pool resolution and we are free to perform this eagerly or lazily?
24-03-2017

Disallowing invokevirtual for private methods would be a simplification, but not sure whether we can add such a constraint. Non-Java languages might employ different resolution rules that apply invokevirtual to private methods - including those of nestmates. I haven't yet tested what the current implementation does.
24-03-2017

I'm not sure what you are getting at with regards to class initialization. Access checking does not require that a class has been initialized. The earliest access checks should occur during verification.
24-03-2017

Do we need to modify the JVMS to clarify that access checking on a member requires that the class has been initialized? That would be 5.5 Initialization. Alternatively we might have to resolve the nest membership at load time rather than at link time, which might get into circularity issues with having to pre-load the nest top.
23-03-2017

I would recommend that we not allow invoke virtual to invoke private methods in the nest, but require invokespecial for this invocation as a step toward a longer-term goal of not allowing invoke virtual to invoke private methods. Agree that get/put field/static do not need any JVMS changes - the access control checks during resolution should handle the changes. Nice.
23-03-2017