Name: vrR10176 Date: 06/28/2001
The CHAPTER 6 "The Java Virtual Machine Instruction Set" of JVM-2 spec says
about invokevirtual instruction:
The unsigned indexbyte1 and indexbyte2 are used to construct an index into the runtime constant
pool of the current class (?3.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 (?184.108.40.206). The method must not be an (*1)
instance initialization method (?3.9) or the class or interface initialization method (?3.9).
Finally, if the resolved method is protected (?4.6), and it is either a member of the current class
or a member of a superclass of the current class, then the class of objectref must be either the
current class or a subclass of the current class.
Let C be the class of objectref. The actual method to be invoked is selected by the following (*2)
If C contains a declaration for an instance method with the same name and descriptor as the resolved
method, and the resolved method is accessible from C, then this is the method to be invoked, and the
lookup procedure terminates.
Otherwise, if C has a superclass, this same lookup procedure is performed recursively using the
direct superclass of C; the method to be invoked is the result of the recursive invocation of this
Otherwise, an AbstractMethodError is raised.
... skip ...
During resolution of the symbolic reference to the method, any of the exceptions pertaining to
method resolution documented in Section 220.127.116.11 can be thrown.
Otherwise, if the resolved method is a class (static) method, the invokevirtual instruction
throws an IncompatibleClassChangeError.
Otherwise, if objectref is null, the invokevirtual instruction throws a NullPointerException.
Otherwise, if no method matching the resolved name and descriptor is selected, invokevirtual
throws an AbstractMethodError. (*3)
Otherwise, if the selected method is abstract, invokevirtual throws an AbstractMethodError.
Otherwise, if the selected method is native and the code that implements the method cannot
be bound, invokevirtual throws an UnsatisfiedLinkError. "
The CHAPTER 6 "Loading, Linking, and Initializing" of JVM-2 spec says
about Method Resolution:
"18.104.22.168 Method Resolution
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 (?22.214.171.124). Therefore, any exceptions
that can be thrown due to 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.
When resolving a method reference:
1.Method resolution checks whether C is a class or an interface.
If C is an interface, method resolution throws an IncompatibleClassChangeError.
2.Method resolution attempts to look up the referenced method in C and its superclasses:
If C declares a method with the name and descriptor specified by the method reference, method
Otherwise, if C has a superclass, step 2 of method lookup is recursively invoked on the direct
superclass of C.
3.Otherwise, method lookup attempts to locate the referenced method in any of the superinterfaces
of the specified class C.
If any superinterface of C declares a method with the name and descriptor specified by the method
reference, method lookup succeeds.
Otherwise, method lookup fails.
If method lookup fails, method resolution throws a NoSuchMethodError. If method lookup succeeds and (*4)
the method is abstract, but C is not abstract, method resolution throws an AbstractMethodError.
Otherwise, if the referenced method is not accessible (?5.4.4) to D, method resolution throws an
According to lookup procedure (see *2) if method lookup fails then AbstractMethodError is raised
(see also assertion *3). But the invokevirtual instruction description says "The named method is
resolved (?126.96.36.199)."(see *1). The section "188.8.131.52 Method Resolution" also describes lookup
procedure and it says "If method lookup fails, method resolution throws a NoSuchMethodError."(see *4).
This looks like a contradiction.
Moreover api spec (jdk1.4.0beta-b69) says about the class java.lang.AbstractMethodError:
"public class AbstractMethodError extends IncompatibleClassChangeError
Thrown when an application tries to call an abstract method. Normally,
this error is caught by the compiler; this error can only occur at run time
if the definition of some class has incompatibly changed since the currently
executing method was last compiled."
So AbstractMethodError may be thrown when an application tries to call an abstract method.
All JDKs since 1.2 throw NoSuchMethodError if method lookup fails. Bug #4306242 against runtime
(Synopsis: NoSuchMethodError instead of AbstractMethodError) was closed as not a bug.
The same issue is with invokespecial instruction.