How a method call is dispatched
Five kinds of call site, five opcodes, and one vtable lookup that picks the body at run time.
Open this lesson in the learning hubKey points
- javac chooses the opcode from the declared type of the receiver. There are four, plus a special case for lambdas.
invokestaticfor static calls;invokespecialfor constructors, private methods andsupercalls.invokevirtualandinvokeinterfacelook the real method up on the object at run time. That is dynamic dispatch.- HotSpot uses a per-class vtable, so a virtual call is one array lookup - and the JIT usually inlines it away entirely.
- A lambda compiles to
invokedynamic. The first execution asks a bootstrap method to spin the implementing class. - Fields are never virtual. A field access is resolved from the declared type, which is why hiding a field is not overriding it.
Example
public class Main {
interface Payment { String label(); }
static class Card implements Payment {
public String label() { return "card"; }
}
static class Amex extends Card {
@Override public String label() { return "amex"; }
}
static int twice(int n) { return n * 2; } // invokestatic
public static void main(String[] args) {
Card asClass = new Amex(); // declared Card, really an Amex
Payment asInterface = new Amex(); // declared Payment, really an Amex
System.out.println("invokestatic twice(21) -> " + twice(21));
System.out.println("invokespecial new Card() -> the constructor, never overridden");
System.out.println("invokevirtual asClass.label() -> " + asClass.label());
System.out.println("invokeinterface asInterface.label() -> " + asInterface.label());
System.out.println();
System.out.println("declared type picked the opcode : " + Card.class.getSimpleName());
System.out.println("runtime class picked the body : " + asClass.getClass().getSimpleName());
System.out.println();
Payment lambda = () -> "lambda";
System.out.println("invokedynamic spins a class the first time this line runs:");
System.out.println(" " + lambda.getClass().getName());
System.out.println(" label() -> " + lambda.label());
}
}
The declared type chooses the opcode; the object chooses the method.
This is a reading copy. The full lesson — with the visual explainer, the interactive lab and a Run button for the code — lives in the JVM course, and every lesson in it is listed on the JVM contents page.