How the Java virtual machine handles method invocation and return
A look under the hood at the bytecodes used for invoking and returning from methods
By Bill Venners, JavaWorld.com, 06/01/97
Page 5 of 5
Invocation instructions and speed
As you might imagine, invoking a method given an interface reference is likely to be slower than invoking a method given a
class reference. When the Java virtual machine encounters an
invokevirtual instruction and resolves the symbolic reference to a direct reference to an instance method, that direct reference is likely
to be an offset into a method table. From that point forward, the same offset can be used. For an
invokeinterface instruction, however, the virtual machine will have to search through the method table every single time the instruction
is encountered, because it can't assume the offset is the same as in previous invocations.
The fastest instructions will most likely be invokespecial and invokestatic, because methods invoked by these instructions are statically bound. When the JVM resolves the symbolic reference for these
instructions and replaces it with a direct reference, that direct reference probably will include a pointer to the actual
bytecodes.
Implementation dependence
All these predictions of speed are to some extent guesses, because individual designers of Java virtual machines can use any
technique to speed things up; they are limited only by their imagination. The data structures and algorithms for resolving
symbolic references and invoking methods are not part of the JVM specification. These decisions are left to the designers
of each Java virtual machine implementation.
For example, the slowest kind of method to invoke traditionally has been the synchronized method, which takes about six times
as long as a non-synchronized method in Sun's 1.1 Java virtual machine. Sun has claimed that its next-generation virtual machine
will make synchronization "free." -- in other words, it will invoke a synchronized method as fast as a non-synchronized one.
Also, Sun's 1.1 virtual machine uses an "interface lookup table" to increase the execution speed of the invokeinterface instruction over that of its 1.0 virtual machine.
Examples of method invocation
The following code illustrates the various ways in which the Java virtual machine invokes methods. The code also shows which
invocation opcode is used in each situation:
interface inYourFace {
void interfaceMethod ();
}
class itsABirdItsAPlaneItsSuperClass implements inYourFace {
itsABirdItsAPlaneItsSuperClass(int i) {
super(); // invokespecial (of an <init>)
}
static void classMethod() {
}
void instanceMethod() {
}
final void finalInstanceMethod() {
}
public void interfaceMethod() {
}
}
class subClass extends itsABirdItsAPlaneItsSuperClass {
subClass() {
this(0); // invokespecial (of an <init>)
}
subClass(int i) {
super(i); // invokespecial (of an <init>)
}
private void privateMethod() {
}
void instanceMethod() {
}
final void anotherFinalInstanceMethod() {
}
void exampleInstanceMethod() {
instanceMethod(); // invokevirtual
super.instanceMethod(); // invokespecial
privateMethod(); // invokespecial
finalInstanceMethod(); // invokevirtual
anotherFinalInstanceMethod(); // invokevirtual
interfaceMethod(); // invokevirtual
classMethod(); // invokestatic
}
}
class unrelatedClass {
public static void main(String args[]) {
subClass sc = new subClass(); // invokespecial (of an <init>)
subClass.classMethod(); // invokestatic
sc.classMethod(); // invokestatic
sc.instanceMethod(); // invokevirtual
sc.finalInstanceMethod(); // invokevirtual
sc.interfaceMethod(); // invokevirtual
inYourFace iyf = sc;
iyf.interfaceMethod(); // invokeinterface
}
Returning from methods
To return from a method, the JVM uses several opcodes, one for each type of return value. These opcodes do not take operands:
If there is a return value, it must be on the operand stack. The return value is popped off the operand stack and pushed onto
the operand stack of the calling method's stack frame. The current stack frame is popped, and the calling method's stack frame
becomes current. The program counter is reset to the instruction following the instruction that invoked this method in the
first place.
Returning from methods
| Opcode |
Operand(s) |
Description |
ireturn
|
none
|
pop int, push onto stack of calling method and return |
lreturn
|
none
|
pop long, push onto stack of calling method and return |
freturn
|
none
|
pop float, push onto stack of calling method and return |
dreturn
|
none
|
pop double, push onto stack of calling method and return |
areturn
|
none
|
pop object reference, push onto stack of calling method and return |
The ireturn instruction is used for methods that return int, char, byte, or short.
About the author
Bill Venners has been writing software
professionally for 12 years. Based in Silicon Valley, he provides
software consulting and training services under the name Artima Software Company. Over the
years he has developed software for the consumer electronics,
education, semiconductor, and life insurance industries. He has
programmed in many languages on many platforms: assembly language
on various microprocessors, C on Unix, C++ on Windows, Java on the
Web. He is author of the book: Inside the
Java Virtual Machine, published by McGraw-Hill. The small print: "How the Java Virtual Machine Handles
Method Invocation and Return" Article Copyright (c) 1997 Bill
Venners. All rights reserved.
Conclusion
Although the subtle differences between the ways a JVM invokes methods can be a bit confusing, understanding these differences
can help you understand the subtleties of the Java language. The main points to remember are:
- Instance methods are dynamically bound except for
<init> methods, private methods, and methods invoked with the super keyword. In these three special cases, instance methods are statically bound.
- Class methods are always statically bound.
- Instance methods invoked with an interface reference may be slower than the same methods invoked with an object reference.
Next month
This month's article left out one detail about method invocation and return: synchronization. Next month, I'll describe how
the Java virtual machine performs thread synchronization, including how it invokes and returns from synchronized methods.