<init>":()V 27: aload 4 29: invokevirtual #7 // Method java/lang #8 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder; 37: invokevirtual #9 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 86: invokevirtual #12 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 82: invokevirtual #12 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 88: invokevirtual
lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 30: iload_2 31: invokevirtual #15 // Method java/lang/ref/SoftReference.get:()Ljava/lang/Object; 80: invokevirtual #10 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 86: invokevirtual #15 // Method java/lang/ref/SoftReference.get:()Ljava/lang/Object; 113: invokevirtual #10 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 119: invokevirtual
<init>":()V 27: aload 4 29: invokevirtual #7 // Method java/lang #8 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder; 37: invokevirtual #9 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 86: invokevirtual #12 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 82: invokevirtual #12 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 88: invokevirtual
L0 LINENUMBER 9 L0 GETSTATIC java/lang/System.out : Ljava/io/PrintStream; LDC "I am try" INVOKEVIRTUAL 注意看这里被复制了 INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V L5 LINENUMBER 14 L5 注意看这里被复制了 INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V L8 LINENUMBER 14 L8 执行 try INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V L6 LINENUMBER 15 L6 执行 finally INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V L7 LINENUMBER 20 L7
程序的时候会进行各种方法调用,虚拟机在执行这些调用的时候会用到不同的字节码指令,共有如下五种: 1. invokespecial:调用私有实例方法; 2. invokestatic:调用静态方法; 3. invokevirtual #5 7: return public void doAction(); Code: 0: getstatic #4 3: ldc #6 5: invokevirtual #5 #9 16: astore_3 17: aload_1 18: pop 19: aload_3 20: invokestatic #10 23: aload_1 24: invokevirtual #9 16: astore_3 17: aload_1 18: pop 19: aload_3 20: invokestatic #10 23: aload_1 24: invokevirtual #9 16: astore_3 17: aload_1 18: pop 19: aload_3 20: invokestatic #10 23: aload_1 24: invokevirtual
// Field java/lang/System.out:Ljava/io/PrintStream; 9: iload_0 10: invokevirtual // Field java/lang/System.out:Ljava/io/PrintStream; 22: iload_1 23: invokevirtual // Field java/lang/System.out:Ljava/io/PrintStream; 37: iload_2 38: invokevirtual // Field java/lang/System.out:Ljava/io/PrintStream; 44: iload_3 45: invokevirtual // Field java/lang/System.out:Ljava/io/PrintStream; 62: iload 4 64: invokevirtual
getIndex(net.sf.cglib.core.Signature arg1) { // Byte code: // 0: aload_1 // 1: invokevirtual 17 java/lang/Object:toString ()Ljava/lang/String; // 4: dup // 5: invokevirtual >70, 1826985398:+72->80, 1913648695:+82->90, 1984935277:+92->100 // 60: ldc 23 // 62: invokevirtual 65: ifeq +46 -> 111 // 68: iconst_1 // 69: ireturn // 70: ldc 29 // 72: invokevirtual 75: ifeq +36 -> 111 // 78: iconst_0 // 79: ireturn // 80: ldc 31 // 82: invokevirtual
<init>":()V 28: aload_3 29: invokevirtual #7 // Method java/lang/StringBuilder.append // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder; 37: invokevirtual #9 <init>":()V 65: ldc #11 // String executeTimeInMillis: 67: invokevirtual #12 // Method java/lang/StringBuilder.append:(J)Ljava/lang/StringBuilder; 77: invokevirtual #9 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 80: invokevirtual
#3 // Field java/lang/System.out:Ljava/io/PrintStream; 10: aload_1 11: invokevirtual 15: if_icmpne 22 18: iconst_1 19: goto 23 22: iconst_0 23: invokevirtual #3 // Field java/lang/System.out:Ljava/io/PrintStream; 14: aload_1 15: invokevirtual 19: if_icmpne 26 22: iconst_1 23: goto 27 26: iconst_0 27: invokevirtual 11: if_icmpne 18 14: iconst_1 15: goto 19 18: iconst_0 19: invokevirtual
// Field java/lang/System.out:Ljava/io/PrintStream; 9: iload_0 10: invokevirtual // Field java/lang/System.out:Ljava/io/PrintStream; 22: iload_1 23: invokevirtual // Field java/lang/System.out:Ljava/io/PrintStream; 37: iload_2 38: invokevirtual // Field java/lang/System.out:Ljava/io/PrintStream; 44: iload_3 45: invokevirtual // Field java/lang/System.out:Ljava/io/PrintStream; 62: iload 4 64: invokevirtual
> //把上面加载的内容作为参数 传递给append方法 14 ldc #6 <hello world> // 从字符串常量池加载hello world 16 invokevirtual #5 <java <init>> 18 aload_1 19 invokevirtual #5 <java/lang/StringBuilder.append> 22 iload_2 23 invokevirtual #6 <java/lang/StringBuilder.append> 26 invokevirtual #7 <java/lang/StringBuilder.toString> 29 astore_1 30 iinc 2 by 1 33 goto 5 (-28) 36 getstatic #8 <java/lang/System.out> 39 aload_1 40 invokevirtual #9 #7 <java/lang/StringBuilder.toString> 37 invokevirtual #9 <java/io/PrintStream.println> 40 return
;)Ljava/lang/StringBuilder; 17: aload_2 18: invokevirtual #10 // Method java/lang/StringBuilder.append : (Ljava/lang/String;)Ljava/lang/StringBuilder; 19: pop 20: aload_3 21: aload_2 22: invokevirtual #10 <init>":()V 17: aload_1 18: invokevirtual #9 // Method java/lang/StringBuilder.append: (Ljava/lang/String ;)Ljava/lang/StringBuilder; 21: iload_2 //将本地变量中下标为2的数字0压入操作栈顶 22: invokevirtual #10 // Method java/lang #11 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 34: invokevirtual #13 // Method
: // 0: aload_0 // 1: getfield 25 mil/uscg/c3cen/vic/aspect/LoggingAspect:file Ljava/io/File; // 4: invokevirtual / 10: aload_0 // 11: getfield 25 mil/uscg/c3cen/vic/aspect/LoggingAspect:file Ljava/io/File; // 14: invokevirtual V // 77: goto +16 -> 93 // 80: astore_2 // 81: aload 6 // 83: ifnull +8 -> 91 // 86: aload 6 // 88: invokevirtual // 116: aload_2 // 117: aload_3 // 118: if_acmpeq +8 -> 126 // 121: aload_2 // 122: aload_3 // 123: invokevirtual )V // 136: aload_2 // 137: athrow // 138: aload 4 // 140: ifnull +66 -> 206 // 143: aload 4 // 145: invokevirtual
<init>":(LMemberCls;)V 21: astore_2 22: aload_1 23: invokevirtual #10 // Method MemberCls$Inner.getVal:()I 34: invokevirtual #11 #10 // Method MemberCls$Inner.getVal:()I 44: invokevirtual #11 #10 // Method MemberCls$Inner.getVal:()I 59: invokevirtual #11 #14 // Method LocalCls$1Inner.getName:()Ljava/lang/String; 41: invokevirtual
程序的时候会进行各种方法调用,虚拟机在执行这些调用的时候会用到不同的字节码指令,共有如下五种: 1. invokespecial:调用私有实例方法; 2. invokestatic:调用静态方法; 3. invokevirtual _1 8: aload_1 9: astore_2 10: aload_1 11: iconst_1 12: iconst_2 13: invokevirtual 18: pop 19: aload_3 20: invokestatic #10 23: aload_1 24: invokevirtual _1 8: aload_1 9: astore_2 10: aload_1 11: iconst_1 12: iconst_2 13: invokevirtual 18: pop 19: aload_3 20: invokestatic #10 23: aload_1 24: invokevirtual
."":()V 7: astore_1 8: aload_1 9: invokevirtual #4 // Method com java/util/Objects.isNull:(Ljava/lang/Object;)Z 15: ifeq 25 18: aload_1 19: invokevirtual ai/center/model/entity/SdAiGroup.getTest:()D 22: goto 29 25: aload_1 26: invokevirtual #9 // Field java/lang/System.err:Ljava/io/PrintStream; 41: aload_2 42: invokevirtual ai/center/model/entity/SdAiGroup.getTest:()D 22: goto 29 25: aload_1 26: invokevirtual
先从字节码看一看区别: // Method // method.invoke(new Super(), false); invokevirtual #37 // Method Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object; // (int)method.invoke(new Super(), false); invokevirtual ;[Ljava/lang/Object;)Ljava/lang/Object; // MethodHandle // mh.bindTo(new MHSuper()).invoke(false); invokevirtual As usual, the Java compiler emits an invokevirtual instruction with the given symbolic type descriptor 综上,MethodHandle更像是在Java语法规则内手写字节码:自己创建方法签名(MethodType),自己决定调用方式(invokestatic/invokespecial/invokevirtual
<init>":()V 10: ldc #6 // String inner run: 12: invokevirtual invokestatic #8 // Method NonStaticInnerDemo.access$000:()Ljava/lang/String; 18: invokevirtual #9 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 24: invokevirtual <init>":()V 10: ldc #5 // String inner run: 12: invokevirtual #8 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 24: invokevirtual
."":()V 7: astore_3 8: aload_3 9: aload_0 10: invokevirtual #11 lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 13: aload_1 14: invokevirtual lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder; 17: aload_2 18: invokevirtual #14 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 29: invokevirtual #14 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 25: invokevirtual
对于类方法调用使用invokestaic指令,而实例方法调用使用invokevirtual指令完成: 操作码 操作数 invokevirtual 而invokevirtual指令执行时,会根据对象实际所属类型来选择调用哪一个方法。 可以简单的理解为虚拟机使用动态绑定来执行invokespecial指令,而对于invokevirtual指令来说,使用的是动态绑定。 只有invokevirtual和invokeinterface指令调用的方法才需要出现在这个方法表中。 invokeVirtual可以通过方法偏移量快速在方法表中定位方法,而invokeInterface则需要每次扫描方法表进行寻找。