invokespecial

Invoke instance method; special handling for superclass, private, and instance initialization method invocations

Bytecode

Type Description
u1 invokespecial opcode = 0xB7 (183)
u2 index

Stack
..., objectref, [arg1, [arg2 ...]] => ...

Description

invokespecial is used in certain special cases to invoke a method Specifically, invokespecial is used to invoke:

the instance initialization method, <init>

a private method of this

a method in a superclass of this

The main use of invokespecial is to invoke an object's instance initialization method, <init>, during the construction phase for a new object. For example, when you write in Java:

new StringBuffer()

code like the following is generated:

new java/lang/StringBuffer         ; create a new StringBuffer
dup                                ; make an extra reference to the new instance
                                   ; now call an instance initialization method
invokespecial java/lang/StringBuffer/<init>()V
                                   ; stack now contains an initialized StringBuffer.
invokespecial is also used by the Java language by the 'super' keyword to access a superclass's version of a method. For example, in the class: 
   class Example {
       // override equals
       public boolean equals(Object x) {
            // call Object's version of equals
            return super.equals(x);
       }
   }
the 'super.equals(x)' expression is compiled to: 
aload_0  ; push 'this' onto the stack
aload_1  ; push the first argument (i.e. x) onto the stack
; now invoke Object's equals() method.
invokespecial java/lang/Object/equals(Ljava/lang/Object;)Z

Finally, invokespecial is used to invoke a private method. Remember that private methods are only visible to other methods belonging the same class as the private method.

Before performing the method invokation, the class and the method identified by <method-spec> are resolved. See Chapter 9 for a description of how methods are resolved.

invokespecial first looks at the descriptor given in <method-spec>, and determines how many argument words the method takes (this may be zero). It pops these arguments off the operand stack. Next it pops objectref (a reference to an object) off the operand stack. objectref must be an instance of the class named in <method-spec>, or one of its subclasses. The interpreter searches the list of methods defined by the class named in <method-spec>, looking for a method called methodname whose descriptor is descriptor. This search is not based on the runtime type of objectref, but on the compile time type given in <method-spec>.

Once a method has been located, invokespecial calls the method. First, if the method is marked as synchronized, the monitor associated with objectref is entered. Next, a new stack frame structure is established on the call stack. Then the arguments for the method (which were popped off the current method's operand stack) are placed in local variables of the new stack frame structure. arg1 is stored in local variable 1, arg2 is stored in local variable 2 and so on. objectref is stored in local variable 0 (the local variable used for the special Java variable this). Finally, execution continues at the first instruction in the bytecode of the new method.

Methods marked as native are handled slightly differently. For native methods, the runtime system locates the platform-specific code for the method, loading it and linking it into the JVM if necessary. Then the native method code is executed with the arguments popped from the operand stack. The exact mechanism used to invoke native methods is implementation-specific.

When the method called by invokespecial returns, any single (or double) word return result is placed on the operand stack of the current method. If the invoked method was marked as synchronized, the monitor associated with objectref is exited. Execution continues at the instruction that follows invokespecial in the bytecode.

Next, the Java Virtual Machine determines if all of the following conditions are true:

If so, then the Java Virtual Machine selects the method with the identical descriptor in the closest superclass, possibly selecting the method just resolved.

The resulting method must not be <clinit>, a class or interface initialization method.

If the method is <init>, an instance initialization method, then the method must only be invoked once on an uninitialized object, and before the first backward branch following the execution of the new instruction that allocated the object.

Finally, if the method is protected , then it must be either a member of the current class or a member of a superclass of the current class, and the class of objectref must be either the current class or a subclass of the current class.

The constant pool entry representing the resolved method includes a direct reference to the code for the method, an unsigned byte nargs that must not be zero, and the method's modifier information.

The objectref must be of type reference and must be followed on the operand stack by nargs - 1 words of arguments, where the number of words of arguments and the type and order of the values they represent must be consistent with the descriptor of the selected instance method.

If the method is synchronized, the monitor associated with objectref is acquired.

If the method is not native, the nargs - 1 words of arguments and objectref are popped from the operand stack. A new stack frame is created for the method being invoked, and objectref and the words of arguments are made the values of its first nargs local variables, with objectref in local variable 0, arg1 in local variable 1, and so on. The new stack frame is then made current, and the Java Virtual Machine pc is set to the opcode of the first instruction of the method to be invoked. Execution continues with the first instruction of the method.

If the method is native and the platform-dependent code that implements it has not yet been loaded and linked into the Java Virtual Machine, that is done. The nargs - 1 words of arguments and objectref are popped from the operand stack; the code that implements the method is invoked in an implementation-dependent manner.

Exception
NullPointerException - objectref is null

StackOverflowError - no more space in callstack for a new stack frame

Notes
The difference between the invokespecial and the invokevirtual instructions is that invokevirtual invokes a method based on the class of the object. The invokespecial instruction is used to invoke instance initialization methods (<init>) as well as private methods and methods of a superclass of the current class.

The invokespecial instruction was named invokenonvirtual prior to Sun's JDK 1.0.2 release.

In Java Virtual Machine implementations prior to version JDK 1.02, this instruction was called invokenonvirtual, and was less restrictive than invokespecial - it wasn't limited to invoking only superclass, private or <init> methods. The class access flag ACC_SUPER (see Chapter 4) is used to indicate which semantics are used by a class. In older class files, the ACC_SUPER flag is unset. In all new classes, the ACC_SUPER flag should be set, indicating that the restrictions enforced by invokespecial are obeyed. (In practice, all the common uses of invokenonvirtual continue to be supported by invokespecial, so this change should have little impact on JVM users).