JVM Spec中关于方法调用的指令有:
例子代码:
import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.util.Arrays; import java.util.List; public class JVMMethodInstruction implements Runnable { static { System.out.println("<clinit>"); } { System.out.println("<init block>"); } public JVMMethodInstruction() {} static void staticMethod() {} static void staticForMethodHandle(String str) {} private void privateMethod() {} void instanceMethod() {} public void forMethodHandle(String str) {} @Override public void run() {} public static void main(String[] args) throws Throwable { /** * invoke special */ JVMMethodInstruction test = new JVMMethodInstruction(); /** * invoke special */ test.privateMethod(); /** * invoke virtual */ test.instanceMethod(); /** * invoke static */ staticMethod(); /** * invoke interface */ Runnable r = test; r.run(); /** * invoke dynamic instance method */ MethodHandles.Lookup lookup = MethodHandles.lookup(); MethodHandle mh = lookup .findVirtual(JVMMethodInstruction.class, "forMethodHandle", MethodType.methodType(void.class, String.class)); System.out.println(mh); mh.bindTo(test).invoke("a"); /** * invoke dynamic static method */ mh = lookup.findStatic(JVMMethodInstruction.class, "staticForMethodHandle", MethodType.methodType(void.class, String.class)); mh.invoke("static"); /** * Java 8中,lambda表达式和默认方法时,底层会生成和使用invoke dynamic * invoke dynamic */ List<Integer> list = Arrays.asList(1, 2, 3, 4); list.stream().forEach(System.out::println); } }
编译然后反编译:
javac JVMMethodInstruction.java javap -c JVMMethodInstruction
得到反编译结果:
public JVMMethodInstruction(); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream; 7: ldc #3 // String <init block> 9: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 12: return public static void main(java.lang.String[]) throws java.lang.Throwable; Code: 0: new #5 // class JVMMethodInstruction 3: dup 4: invokespecial #6 // Method "<init>":()V 7: astore_1 8: aload_1 9: invokespecial #7 // Method privateMethod:()V 12: aload_1 13: invokevirtual #8 // Method instanceMethod:()V 16: invokestatic #9 // Method staticMethod:()V 19: aload_1 20: astore_2 21: aload_2 22: invokeinterface #10, 1 // InterfaceMethod java/lang/Runnable.run:()V 27: invokestatic #11 // Method java/lang/invoke/MethodHandles.lookup:()Ljava/lang/invoke/MethodHandles$Lookup; 30: astore_3 31: aload_3 32: ldc #5 // class JVMMethodInstruction 34: ldc #12 // String forMethodHandle 36: getstatic #13 // Field java/lang/Void.TYPE:Ljava/lang/Class; 39: ldc #14 // class java/lang/String 41: invokestatic #15 // Method java/lang/invoke/MethodType.methodType:(Ljava/lang/Class;Ljava/lang/Class;)Ljava/lang/invoke/MethodType; 44: invokevirtual #16 // Method java/lang/invoke/MethodHandles$Lookup.findVirtual:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle; 47: astore 4 49: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream; 52: aload 4 54: invokevirtual #17 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V 57: aload 4 59: aload_1 60: invokevirtual #18 // Method java/lang/invoke/MethodHandle.bindTo:(Ljava/lang/Object;)Ljava/lang/invoke/MethodHandle; 63: ldc #19 // String a 65: invokevirtual #20 // Method java/lang/invoke/MethodHandle.invoke:(Ljava/lang/String;)V 68: aload_3 69: ldc #5 // class JVMMethodInstruction 71: ldc #21 // String staticForMethodHandle 73: getstatic #13 // Field java/lang/Void.TYPE:Ljava/lang/Class; 76: ldc #14 // class java/lang/String 78: invokestatic #15 // Method java/lang/invoke/MethodType.methodType:(Ljava/lang/Class;Ljava/lang/Class;)Ljava/lang/invoke/MethodType; 81: invokevirtual #22 // Method java/lang/invoke/MethodHandles$Lookup.findStatic:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle; 84: astore 4 86: aload 4 88: ldc #23 // String static 90: invokevirtual #20 // Method java/lang/invoke/MethodHandle.invoke:(Ljava/lang/String;)V 93: iconst_4 94: anewarray #24 // class java/lang/Integer 97: dup 98: iconst_0 99: iconst_1 100: invokestatic #25 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; 103: aastore 104: dup 105: iconst_1 106: iconst_2 107: invokestatic #25 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; 110: aastore 111: dup 112: iconst_2 113: iconst_3 114: invokestatic #25 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; 117: aastore 118: dup 119: iconst_3 120: iconst_4 121: invokestatic #25 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; 124: aastore 125: invokestatic #26 // Method java/util/Arrays.asList:([Ljava/lang/Object;)Ljava/util/List; 128: astore 5 130: aload 5 132: invokeinterface #27, 1 // InterfaceMethod java/util/List.stream:()Ljava/util/stream/Stream; 137: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream; 140: dup 141: invokevirtual #28 // Method java/lang/Object.getClass:()Ljava/lang/Class; 144: pop 145: invokedynamic #29, 0 // InvokeDynamic #0:accept:(Ljava/io/PrintStream;)Ljava/util/function/Consumer; 150: invokeinterface #30, 2 // InterfaceMethod java/util/stream/Stream.forEach:(Ljava/util/function/Consumer;)V 155: return