Lambda Specification, Part J: Java Virtual Machine

Navigation: Overview - Part A - Part B - Part C - Part D - Part E - Part F - Part G - Part H - Part J
Sections: JVMS-4.6 - JVMS-4.9.1 - JVMS-4.9.2 - JVMS-4.4.8 - JVMS-5.4.3.3 - JVMS-5.4.3.4 - JVMS-5.4.5 - JVMS-6.5.invokeinterface - JVMS-6.5.invokespecial - JVMS-6.5.invokestatic - JVMS-6.5.invokevirtual
Version 0.9.1. Copyright © 2013 Oracle America, Inc. Legal Notice.

Summary

Changes to the Java Virtual Machine are necessary to support the implementation of default methods. Methods declared in interface class files need not be declared abstract, and thus can carry a Code attribute. Methods declared in interface class files may also be private or static. The invokespecial and invokestatic instructions may refer to interface methods. The rules for method resolution and invocation (via invokeinterface, invokespecial, invokestatic, and invokevirtual) are enhanced to support execution of code in interfaces.

JVMS 4.6 Methods [Modified]

Compare JVMS 4.6

...

Methods of classes may set any of the flags in Table 4.5. However, a specific method of a class may have at most one of its ACC_PRIVATE, ACC_PROTECTED, and ACC_PUBLIC flags set (8.4.3). [jvms-4.6-200-A.5]

Methods of interfaces may set any of the flags in Table 4.5 except ACC_PROTECTED, ACC_FINAL, ACC_NATIVE, and ACC_SYNCHRONIZED (9.4); they must have exactly one of the ACC_PUBLIC or ACC_PRIVATE flags set. [jsr335-4.6-200-A.10]

An interface method in a class file whose version number is not 52.0 or above must have its ACC_ABSTRACT and ACC_PUBLIC flags set they may have their ACC_VARARGS, ACC_BRIDGE, and ACC_SYNTHETIC flags set and must not have any of the other flags in Table 4.5 set (9.4). [jvms-4.6-200-A.6]

If a specific method of a class or interface has its ACC_ABSTRACT flag set, it must not have any of its ACC_FINAL, ACC_NATIVE, ACC_PRIVATE, ACC_STATIC, ACC_STRICT, or ACC_SYNCHRONIZED flags set (8.4.3.1, 8.4.3.3, 8.4.3.4). [jsr335-4.6-200-A.11]

...

Discussion and motivation:

Interface methods prior to version 52.0 must be abstract, and thus must not be private, static, or strictfp; they are also prohibited from having Code attributes (4.7.3). In version 52.0, an interface method may be non-abstract and thus is free to use these flags and have a Code attribute.

JVMS 4.9.1 Static Constraints [Modified]

Compare JVMS 4.9.1

...

The static constraints on the operands of instructions in the code array are as follows: [jvms-4.9.1-120]

...

...

Discussion and motivation:

In order to invoke static and private methods in interfaces, InterfaceMethodrefs must be supported by the invokestatic and invokespecial instructions. In addition, this change allows non-static, non-abstract methods appearing in a direct superinterface to be invoked via invokespecial.

JVMS 4.9.2 Structural Constraints [Modified]

Compare JVMS 4.9.2

The structural constraints on the code array specify constraints on relationships between Java virtual machine instructions. The structural constraints are as follows: [jvms-4.9.2-100]

...

...

Discussion and motivation:

  1. A clause is added to support invokespecial of default methods in a superinterface. References to a superinterface method must point to a direct superinterface; this is in contrast to references to a superclass method, which can point to any superclass. This is because i) the search path for a closer match of an interface method (as required by the ACC_SUPER flag) is not clear if the reference is not to a direct superinterface, and ii) there is no practical need for more flexibility (note that a reference can resolve to a method in an ancestor interface, even if the interface is not named directly). In retrospect, the ideal probably would have been to make a similar restriction on invocations of superclass methods.
  2. The introduction of phrases like "referenced in" is a clarification of existing behavior: the check is against the class appearing in the Methodref or InterfaceMethodref, not the declaring class of the resolved method.

JVMS 4.4.8 The CONSTANT_MethodHandle_info Structure [Modified]

Compare JVMS 4.4.8

...

If the value of the reference_kind item is 5 (REF_invokeVirtual) 6 (REF_invokeStatic), 7 (REF_invokeSpecial), or 8 (REF_newInvokeSpecial), then the constant_pool entry at that index must be a CONSTANT_Methodref_info (4.4.2) structure representing a class's method or constructor (2.9) for which a method handle is to be created. [jvms-4.4.8-200-C.2]

If the value of the reference_kind item is 6 (REF_invokeStatic) or 7 (REF_invokeSpecial), then the constant_pool entry at that index must be either a CONSTANT_Methodref_info structure or, if the constant pool appears in a class file whose version number is 52.0 or above, a CONSTANT_InterfaceMethodref (4.4.2) structure representing a class's or interface's method for which a method handle is to be created. [jsr335-4.4.8-200-C.6]

If the value of the reference_kind item is 9 (REF_invokeInterface), then the constant_pool entry at that index must be a CONSTANT_InterfaceMethodref_info (4.4.2) structure representing an interface's method for which a method handle is to be created. [jsr335-4.4.8-200-C.3]

...

JVMS 5.4.3.3 Method Resolution [Modified]

Compare JVMS 5.4.3.3

To resolve an unresolved symbolic reference from D to a method in a class C, the symbolic reference to C given by the method reference is first resolved (5.4.3.1). Therefore, any exception that can be thrown as a result of failure of resolution of a class reference can be thrown as a result of method resolution. If the reference to C can be successfully resolved, exceptions relating to the resolution of the method reference itself can be thrown. [jvms-5.4.3.3-100]

When resolving a method reference: [jvms-5.4.3.3-200]

A maximally-specific superinterface method of a class or interface C for a particular method name and descriptor is any method for which the following conditions hold: [jsr335-5.4.3.3-25]

If method lookup fails, method resolution throws a NoSuchMethodError. [jvms-5.4.3.3-210-A]

If method lookup succeeds and the method is abstract, but C is not abstract, method resolution throws an AbstractMethodError. [jvms-5.4.3.3-210-B]

Otherwise, if If method lookup succeeds and the referenced method is not accessible (5.4.4) to D, method resolution throws an IllegalAccessError. [jvms-5.4.3.3-210-C]

...

Discussion and motivation:

  1. When resolution searches for a method in the class's superinterfaces, we prefer to identify a maximally-specific non-abstract method. This is because it is possible that this is the method that will be selected and invoked by an invoke instruction, and so we want to ensure that class loader constraints are performed for this method.

    Otherwise, the result is nondeterministic. This is not new: the specification has never identified exactly which method is chosen, and how "ties" should be broken. In the past, this was mostly an unobservable distinction. However, now that the set of interface methods is more heterogenous, care must be taken to avoid more serious problems with nondeterministic behavior.

    Thus:

    • Superinterface methods that are private and static are ignored by resolution. This is consistent with the Java language view of these declarations, which says that they are not inherited. They can still be referenced, of course, by directly naming the interface in which they are declared, via an InterfaceMethodref. (In retrospect, it might be more consistent with the Java language to give the same treatment to private methods in classes...)
    • Any behavior controlled by the resolved method should not depend on whether the method is abstract or not.
  2. The check that the resolved method is not abstract unless the named class is also abstract has been removed. This is a rather ad hoc check, and conflicts with the nondeterministic choice of interface methods, as explained above. The effect of removing the check is to allow abstract methods in non-abstract classes to be invoked, assuming that the object for the invocation has a concrete implementation of the method.

    This change is retroactive for all class versions.

JVMS 5.4.3.4 Interface Method Resolution [Modified]

Compare JVMS 5.4.3.4

To resolve an unresolved symbolic reference from D to an interface method in an interface C, the symbolic reference to C given by the interface method reference is first resolved (5.4.3.1). Therefore, any exception that can be thrown as a result of failure of resolution of an interface reference can be thrown as a result of interface method resolution. If the reference to C can be successfully resolved, exceptions relating to the resolution of the method reference itself can be thrown. [jvms-5.4.3.4-100]

When resolving an interface method reference: [jvms-5.4.3.4-200]

If method lookup succeeds and the referenced method is not accessible (5.4.4) to D, method resolution throws an IllegalAccessError. [jsr335-5.4.3.4-210]

...

Discussion and motivation:

  1. The clause about access is added because resolution may pick a private method of interface C.
  2. An oversight in previous iterations of the JVM Specification allowed non-public and static methods of the class Object to be the result of interface method resolution. Such results were not consistent with the Java language's inheritance model (see 9.2), nor were they properly handled downstream (such as in the specification for invokeinterface). This is corrected by disallowing resolution to such methods.

JVMS 5.4.5 Method Overriding [Modified]

Compare JVMS 5.4.5

An instance method m1 declared in a class C overrides another instance method m2 declared in a class A iff either m1 is the same as m2, or all of the following are true: [jvms-5.4.5-100]

Discussion and motivation:

This is a bug fix to make the specification consistent with longstanding VM behavior, which is to skip over private methods during selection. (It also clarifies that private methods can be considered to "override" themselves.)

JVMS 6.5 invokeinterface [Modified]

Compare JVMS 6.5.invokeinterface

...

Let C be the class of objectref. The actual method to be invoked is selected by the following lookup procedure: [jvms-6.5.invokeinterface.desc-200]

...

During resolution of the symbolic reference to the interface method, any of the exceptions pertaining to interface method resolution (JVMS-5.4.3.4) can be thrown. [jvms-6.5.invokeinterface.linking-100]

Otherwise, if the resolved method is a static method, the invokeinterface instruction throws an IncompatibleClassChangeError. [jsr335-6.5.invokeinterface.linking-20]

Otherwise, if the resolved method is a private method, the invokeinterface instruction throws an IncompatibleClassChangeError. [jsr335-6.5.invokeinterface.linking-22]

Otherwise, if objectref is null, the invokeinterface instruction throws a NullPointerException. [jsr335-6.5.invokeinterface.runtime-100]

Otherwise, if the class of objectref does not implement the resolved interface, invokeinterface throws an IncompatibleClassChangeError. [jsr335-6.5.invokeinterface.runtime-110]

Otherwise, if no method matching the resolved name and descriptor is selected, invokeinterface throws an AbstractMethodError. [jsr335-6.5.invokeinterface.runtime-120]

Otherwise, if the selected method is not public, invokeinterface throws an IllegalAccessError. [jsr335-6.5.invokeinterface.runtime-130]

Otherwise, if the selected method is abstract, invokeinterface throws an AbstractMethodError. [jsr335-6.5.invokeinterface.runtime-140]

Otherwise, if the selected method is native ... [jsr335-6.5.invokeinterface.runtime-150]

Discussion and motivation:

  1. The selection logic is modified so that a non-abstract method declared in a superinterface may be selected. By design, this change is retroactive: an invokeinterface occurring in an old class file may have the effect of invoking a non-abstract interface method declared in a new class file.

    Methods in interfaces are only considered if there is no matching method in the class hierarchy.

    In the event that we must choose between two non-abstract methods in the superinterface hierarchy, with neither more specific than the other, an error occurs. We do not attempt to disambiguate (for example, one may be the referenced method and one may be unrelated, but we do not prefer the referenced method).

    On the other hand, if there are many abstract methods but only one non-abstract method, the non-abstract method is chosen (unless an abstract method is more specific).

    Like method resolution, method selection ignores private and static methods declared in superinterfaces.

  2. Like invokevirtual, invokeinterface does not allow the resolved method to be static (this was impossible in previous versions, assuming the class Object has no static methods). Since private interface methods cannot be selected, we similarly report an error if the resolved method is private.
  3. Given the restructured selection logic, it is no longer necessary to separately mandate an AbstractMethodError if nothing is found. So that clause has been removed (but the behavior in that case is unchanged).

JVMS 6.5 invokespecial [Modified]

Compare JVMS 6.5.invokespecial

...

The unsigned indexbyte1 and indexbyte2 are used to construct an index into the runtime constant pool of the current class (2.6), where the value of the index is (indexbyte1 << 8) | indexbyte2. The runtime constant pool item at that index must be a symbolic reference to a method or an interface method (5.1), which gives the name and descriptor (4.3.3) of the method as well as a symbolic reference to the class or interface in which the method is to be found. The named method is resolved (5.4.3.3, 5.4.3.4). Finally, if the resolved method is protected (4.6), and it is a member of a superclass of the current class, and the method is not declared in the same runtime package (5.3) as the current class, then the class of objectref must be either the current class or a subclass of the current class, or an IllegalAccessError is raised. [jvms-6.5.invokespecial.desc-100]

Next, the resolved a method is selected for invocation according to the following rules. [jsr335-6.5.invokespecial.desc-150]

Let C be the class or interface named by the method reference or interface method reference, unless all of the following conditions are true: [jvms-6.5.invokespecial.desc-200]

If the above conditions are true, the actual method to be invoked is selected by the following lookup procedure let C, instead, be the direct superclass of the current class. [jsr335-6.5.invokespecial.desc-210]

The method for invocation is selected as follows: [jvms-6.5.invokespecial.desc-300]

...

Otherwise, if objectref is null, the invokespecial instruction throws a NullPointerException. [jvms-6.5.invokespecial.runtime-100]

Otherwise if no method matching the resolved name and descriptor is selected, invokespecial throws an AbstractMethodError. [jvms-6.5.invokespecial.runtime-110]

Otherwise, if the selected method is abstract, invokespecial throws an AbstractMethodError. [jvms-6.5.invokespecial.runtime-120]

Otherwise, if the selected method is native ... [jvms-6.5.invokespecial.runtime-130]

Discussion and motivation:

  1. The invokespecial instruction is extended to:
    • Handle invocation of a private interface method.
    • Handle invocation of a non-abstract interface method referenced via a direct superinterface.
    • Handle invocation of a non-abstract interface method referenced via a superclass.

    In these cases, the rules for selection are essentially the same as those for invokeinterface (except that the search starts from a different class).

    For simplicity of presentation, the selection logic has been changed to apply in all cases. Sometimes this is redundant—in fact, with the exception of the ACC_SUPER trick performed for indirect superclass invocations, if selection produces a method, it will be the resolved method. But, selection must also ensure that appropriate error checks (such as the IncompatibleClassChangeError) are performed, to avoid nondeterminism.

  2. The behavior of selection has been clarified slightly to account for the possibility that the Methodref resolves to an interface method, but this method has a closer match in a superclass.
    public interface I { public abstract void m(); }
    public abstract class A implements I {}
    public class B extends A { public void m() { ... } }
    public class C extends B {
      public void test() {
        invokespecial A.m()V;
      }
    }
    

    The previous specification text suggested that this would be an AbstractMethodError, since since I is not "a superclass of the current class". However, the behavior of the HotSpot VM here has been to select B.m.

JVMS 6.5 invokestatic [Modified]

Compare JVMS 6.5.invokestatic

...

The unsigned indexbyte1 and indexbyte2 are used to construct an index into the runtime constant pool of the current class (2.6), where the value of the index is (indexbyte1 << 8) | indexbyte2. The runtime constant pool item at that index must be a symbolic reference to a method or an interface method (5.1), which gives the name and descriptor (4.3.3) of the method as well as a symbolic reference to the class or interface in which the method is to be found. The named method is resolved (5.4.3.3). The resolved method must not be an instance initialization method (2.9) or the a class or interface initialization method (2.9). It must be static, and therefore cannot be abstract. [jvms-6.5.invokestatic.desc-100]

On successful resolution of the method, the class or interface that declared the resolved method is initialized (5.5) if that class or interface has not already been initialized. [jvms-6.5.invokestatic.desc-110]

...

Otherwise, if the resolved method is an instance method, the invokestatic instruction throws an IncompatibleClassChangeError. [jvms-6.5.invokestatic.linking-110]

Otherwise, if execution of this invokestatic instruction causes initialization of the referenced class or interface, invokestatic may throw an Error as detailed in 5.5. [jvms-6.5.invokestatic.runtime-100]

...

Discussion and motivation:

The invokestatic instruction is extended to handle invocation of a static interface method.

JVMS 6.5 invokevirtual [Modified]

Compare JVMS 6.5.invokevirtual

...

The unsigned indexbyte1 and indexbyte2 are used to construct an index into the runtime constant pool of the current class (2.6), where the value of the index is (indexbyte1 << 8) | indexbyte2. The runtime constant pool item at that index must be a symbolic reference to a method (5.1), which gives the name and descriptor (4.3.3) of the method as well as a symbolic reference to the class in which the method is to be found. The named method is resolved (5.4.3.3). The resolved method must not be an instance initialization method (2.9) or the a class or interface initialization method (2.9). Finally, if the resolved method is protected (4.6), and it is a member of a superclass of the current class, and the method is not declared in the same runtime package (5.3) as the current class, then the class of objectref must be either the current class or a subclass of the current class. [jvms-6.5.invokevirtual.desc-100]

If the resolved method is not signature polymorphic (2.9), then the invokevirtual instruction proceeds as follows. [jvms-6.5.invokevirtual.desc-200]

Let C be the class of objectref. The actual method to be invoked is selected by the following lookup procedure: [jvms-6.5.invokevirtual.desc-210]

...

Otherwise, if the resolved method is not signature polymorphic: [jvms-6.5.invokevirtual.runtime-110]

...

Discussion and motivation:

  1. It is possible that the Methodref of an invokevirtual instruction resolves to an interface method. In this case, it is possible that there is no overriding method in the class hierarchy, but that a non-abstract interface method matches the resolved method's signature. The selection logic has been modified to match such a method, using the same rules as those for invokeinterface.

    Again, this change is designed to be retroactive: an invokevirtual occurring in an old class file may have the effect of invoking a non-abstract interface method declared in a new class file.

  2. Given the restructured selection logic, it is no longer necessary to separately mandate an AbstractMethodError if nothing is found. So that clause has been removed (but the behavior in that case is unchanged).