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 (§184.108.40.206). 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 failure 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. When resolving a method reference: 1. If C is an interface, method resolution throws an IncompatibleClassChangeError. 2. Otherwise, method resolution attempts to locate the referenced method in C and its superclasses:
If C declares exactly one method with the name specified by the method reference, and the declaration is a signature polymorphic method (§2.9.3), then method lookup succeeds. All the class names mentioned in the descriptor are resolved (§220.127.116.11).
The resolved method is the signature polymorphic method declaration. It is not necessary for C to declare a method with the descriptor specified by the method reference.
Otherwise, if C declares a method with the name and descriptor specified by the method reference, method lookup succeeds.
Otherwise, if C has a superclass, step 2 of method resolution is recursively invoked on the direct superclass of C.
Otherwise, method resolution attempts to locate the referenced method in the superinterfaces of the specified class C:
If the maximally-specific superinterface methods of C for the name and descriptor specified by the method reference include exactly one method that does not have its ACC_ABSTRACT flag set, then this method is chosen and method lookup succeeds.
Otherwise, if any superinterface of C declares a method with the name and descriptor specified by the method reference that has neither its ACC_PRIVATE flag nor its ACC_STATIC flag set, one of these is arbitrarily chosen and method lookup succeeds.
Otherwise, method lookup fails. A maximally-specific superinterface method of a class or interface C for a particular method name and descriptor is any method for which all of the following are true:
The method is declared in a superinterface (direct or indirect) of C.
The method is declared with the specified name and descriptor.
The method has neither its ACC_PRIVATE flag nor its ACC_STATIC flag set.
Where the method is declared in interface I, there exists no other maximally-specific superinterface method of C with the specified name and descriptor that is declared in a subinterface of I. The result of method resolution is determined as follows:
If method lookup failed, method resolution throws a NoSuchMethodError.
Otherwise, method lookup succeeded. Access control is applied for the access from D to the method which is the result of method lookup (§5.4.4). Then:
If access control failed, method resolution fails for the same reason.
Otherwise, access control succeeded. Loading constraints are imposed, as follows.
Let <E, L1> be the class or interface in which the referenced method m is actually declared. Let L2 be the defining loader of D. Given that the return type of m is Tr, and that the formal parameter types of m are Tf1, …, Tfn:
If Tr is not an array type, let T0 be Tr; otherwise, let T0 be the element type of Tr.
For i = 1 to n: If Tfi is not an array type, let Ti be Tfi; otherwise, let Ti be the element type of Tfi.
The Java Virtual Machine imposes the loading constraints TiL1 = TiL2 for i = 0 to n.
If imposing these constraints results in any loading constraints being violated (§5.3.4), then method resolution fails. Otherwise, method resolution succeeds. When resolution searches for a method in the class’s superinterfaces, the best outcome is to identify a maximally-specific non-abstract method. It is possible that this method will be chosen by method selection, so it is desirable to add class loader constraints for it. Otherwise, the result is nondeterministic. This is not new: The Java® Virtual Machine Specification has never identified exactly which method is chosen, and how "ties" should be broken. Prior to Java SE 8, this was mostly an unobservable distinction. However, beginning with Java SE 8, the set of interface methods is more heterogenous, so care must be taken to avoid problems with nondeterministic behavior. Thus:
Superinterface methods that are private and static are ignored by resolution. This is consistent with the Java programming language, where such interface methods are not inherited.
Any behavior controlled by the resolved method should not depend on whether the method is abstract or not. Note that if the result of resolution is an abstract method, the referenced class C may be non-abstract. Requiring C to be abstract would conflict with the nondeterministic choice of superinterface methods. Instead, resolution assumes that the run time class of the invoked object has a concrete implementation of the method.