JEP 181 proposes changes to the Java Virtual Machine Specification to allow access to private class members from related "nestmate" classes. This document proposes accompanying changes to the Java Language Specification in order to accurately describe the new runtime behavior of method invocation.

For programs that contain consistently-compiled classes, there is no change in language behavior.

13.1 The Form of a Binary

...

A binary representation for a class or interface must also contain all of the following:

...

  1. Every nested class and nested interface must have a symbolic reference to each of its immediately enclosing class enclosing classes (8.1.3).

  2. Every class must contain symbolic references to all of its member types (8.5), and to all local and anonymous classes that appear in its methods, constructors, static initializers, instance initializers, and field initializers.

    Every interface must contain symbolic references to all of its member types (9.5), and to all local and anonymous classes that appear in its default methods and field initializers.

It was already true that deeply-nested classes would refer to all of their enclosing classes (per the specification of the InnerClasses attribute). We state that here for clarity. The NestHost attribute can refer to the top-level enclosing class without adding any new references to the class file.

We could also assert that a top-level class contains references to each of its enclosed classes, no matter how deeply nested. But this is not true of the InnerClasses attribute, and we do not wish to force implementations to use the NestMembers attribute. They are free to do so if they wish.

...

15.12.3 Compile-Time Step 3: Is the Chosen Method Appropriate?

...

The following compile-time information is then associated with the method invocation for use at run time:

We no longer use the nonvirtual invocation mode. private method invocations have invocation mode virtual and behave just like other method invocations. (With the caveat that, per the rules below, a private method will be selected directly without performing a search for a different overriding method.)

...

15.12.4.4 Locate Method to Invoke

The strategy for method lookup depends on the invocation mode.

As in section 15.12.4.3, let T be the qualifying type of the method invocation, let m be the method found in T or a supertype of T, and let C be the class or interface that declares m.

If the invocation mode is static, no target reference is needed and overriding is not allowed. Method m of class T class or interface C is the one to be invoked.

Otherwise, an instance method is to be invoked and there is a target reference. If the target reference is null, a NullPointerException is thrown at this point. Otherwise, the target reference is said to refer to a target object and will be used as the value of the keyword this in the invoked method. The other four three possibilities for the invocation mode are then considered.

If the invocation mode is nonvirtual, overriding is not allowed. Method m of class T is the one to be invoked.

If the invocation mode is super, then method m of class or interface C is the one to be invoked. If m is abstract, an AbstractMethodError is thrown.

This is a simplification not directly tied to nestmates: we already located m in T or a supertype of T (15.12.4.3). There is no need to do so again as part of a "dynamic lookup process", as described below.

Otherwise, if the invocation mode is virtual, and T and m jointly indicate a signature polymorphic method (15.12.3), then the target object is an instance of java.lang.invoke.MethodHandle or java.lang.invoke.VarHandle. The target object encapsulates state which is matched against the information associated with the method invocation at compile time. Details of this matching are given in The Java Virtual Machine Specification, Java SE 9 Edition and the Java SE Platform API. If matching succeeds, then either the method referenced by the java.lang.invoke.MethodHandle instance is directly and immediately invoked, or the variable represented by the java.lang.invoke.VarHandle instance is directly and immediately accessed, and in either case the procedure in 15.12.4.5 is not executed. If matching fails, then a java.lang.invoke.WrongMethodTypeException is thrown.

Otherwise, the invocation mode is interface or virtual.

If the method m of class or interface C is private, then it is the method to be invoked.

Otherwise, the invocation mode is interface, virtual, or super, and overriding may occur. A and a dynamic method lookup is used. The dynamic lookup process starts from a class S, determined as follows: R, the actual run-time class of the target object.

This is true even if the target object is an array instance. (Note that for invocation mode interface, R necessarily implements T; for invocation mode virtual, R is necessarily either T or a subclass of T.)

Note that for invocation mode interface, R necessarily implements T; for invocation mode virtual, R is necessarily either T or a subclass of T. If the target object is an array, then R is a "class" representing an array type.

The dynamic method lookup uses the following procedure to search class S, and then the superclasses and superinterfaces of class S, as necessary, for method m.

Let X be the compile-time type of the target reference of the method invocation. Let S be a class to search, beginning with R. Then:

  1. If class S contains a declaration for a method named m with the same descriptor (same number of parameters, the same parameter types, and the same return type) required by the method invocation as determined at compile time (15.12.3), then: that overrides method m of class or interface C from R (8.4.8.1), then that overriding method is the method to be invoked, and the procedure terminates.
  1. Otherwise, if S has a superclass, the lookup procedure of steps 1 and 2 is performed recursively using the direct superclass of S in place of S; the method to be invoked, if any, is the result of the recursive invocation of this lookup procedure.

  2. If no method is found by the previous two steps, the superinterfaces of S are searched for a suitable method.

    A set of candidate methods is considered with the following properties: i) each method is declared in a (direct or indirect) superinterface of S R; ii) each method has the name and descriptor required by the method invocation; iii) each method is non-static and non-private; iv) for each method, where the method's declaring interface is I, there is no other method satisfying (i) through (iii) that is declared in a subinterface of I.

    If this set contains a default method, one such method is the method to be invoked. Otherwise, an abstract method in the set is selected as the method to be invoked.

Dynamic method lookup may cause the following errors to occur:

The above procedure (if it terminates without error) will find a non-abstract, accessible method to invoke, provided that all classes and interfaces in the program have been consistently compiled. However, if this is not the case, then various errors may occur, as specified above; additional details about the behavior of the Java Virtual Machine under these circumstances are given by The Java Virtual Machine Specification, Java SE 9 Edition.

The dynamic lookup process, while described here explicitly, will often be implemented implicitly, for example as a side-effect of the construction and use of per-class method dispatch tables, or the construction of other per-class structures used for efficient dispatch.

These rules are intended to faithfully reflect the JVMS definition of method selection, as proposed by JEP 181, in section 5.4.5.

...