JVM method dispatch

来自WHY42

Method invocation

invokestatic

invoke a static method:

invokestatic
indexbyte1
indexbyte2

invoke a static method, the method is from the constant pool by

index= (indexbyte1 << 8) | indexbyte2
public class Hello {
    public static void sayHello(String msg) {
        System.out.println(msg);
    }

    public static void main(String[] args) {
        sayHello("Riguz!");
    }
}

compiled:

// Riguz!
#4 = String             #23
// com/riguz/Hello.sayHello:(Ljava/lang/String;)V
#5 = Methodref          #6.#24 
...
  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=1, locals=1, args_size=1
         0: ldc           #4
         2: invokestatic  #5
         5: return
      LineNumberTable:
        line 9: 0
        line 10: 5
}

invokevirtual

Invoke instance method; dispatch based on class

invokevirtual
indexbyte1
indexbyte2

Operand stack:

..., objectref, [arg1, [arg2 ...]] →
// java/lang/System.out:Ljava/io/PrintStream;
#2 = Fieldref           #19.#20
// java/io/PrintStream.println:(Ljava/lang/String;)V   
#3 = Methodref          #21.#22   
...       
  public static void sayHello(java.lang.String);
    descriptor: (Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=1, args_size=1
         0: getstatic     #2
         3: aload_0
         4: invokevirtual #3
         7: return

invokespecial

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

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

  public HelloWorld();
    descriptor: ()V
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 1: 0
public static HelloWorld create() {
    HelloWorld h = new HelloWorld();
    return h;
}
  public static HelloWorld create();
    descriptor: ()LHelloWorld;
    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=1, args_size=0
         0: new           #2                  // class HelloWorld
         3: dup
         4: invokespecial #3                  // Method "<init>":()V
         7: astore_0
         8: aload_0
         9: areturn
      LineNumberTable:
        line 3: 0
        line 4: 8

invokeinterface

public static void main(String[] args) {
    SayHello s = new HelloWorld();
    s.hi();
}
  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=2, args_size=1
         0: new           #5                  // class HelloWorld
         3: dup
         4: invokespecial #6                  // Method "<init>":()V
         7: astore_1
         8: aload_1
         9: invokeinterface #7,  1            // InterfaceMethod SayHello.hi:()V
        14: return

invokedynamic