Search code examples
javajvmjavacmethod-call

Javac Implementation: What jvm instructions does a method call produce?


Assuming I have a method call site in java. What is the equivalent jvm bytecode (apart frm the call which is translated to invokevirtual/static e.t.c)? I'm more interested in the commands that load the receiver on the stack.

-Obviously one command is aload.

-Another could be that another invocation returns a refobject on the stack

-Three, the new instruction. (e.g new A().foo(). It gets dupped. But the dupped is consumed by the constructor)

-four, maybe(??) Dup. (when having a.foo(); a.bar(); Is There a chance the compiler will produce aload then dup instead of aload aload?)

My biggest question is the rest dup commands. Because they kind of shuffle the stack. when does javac produce them? Does it use them when compiling a call site?

I've tried to find documentations without luck. Then found the source code, but it's going to take days to dig into that. I believe the Code.java and Gen.java files are responsible for the translation/compilation process.


Solution

  • Almost any bytecode instruction that produces a reference can be used by javac to load a receiver.

    • aload, invokeX, new + dup
      Those you already mentioned.
    • getfield, getstatic

      field.method();
      
    • aaload

      arr[index].method();
      
    • anewarray

      (new Object[0]).hashCode();
      
    • multianewarray

      (new byte[5][10]).getClass();
      
    • checkcast

      ((List) obj).size();
      
    • ldc

      MyClass.class.getName();
      
    • aconst_null

      ((Object) null).getClass();
      
    • dup

      IntSupplier s = field::hashCode;
      

      Here dup + invokevirtual are used to emit a tricky null-check:

      getstatic     #2      // Field field:Ljava/lang/String;
      dup
      invokevirtual #3      // Method java/lang/Object.getClass:()Ljava/lang/Class;
      pop
      invokedynamic #4,  0  // InvokeDynamic #0:getAsInt