Tomcat8优化--JVM字节码
JVM字节码
1、通过javap命令查看class文件的字节码内容
1.1 创建一个简单的测试类
public class Test1 { public static void main(String[] args) { int a = 2; int b = 5; int c = b-a; System.out.println(c); } }
执行成功target目录下便会生成class文件:
1.2 cmd 使用命令
javap -v Test1.class > Test1.txt
执行成功相应目录下生成Test1.txt文件:
1.3 查看Test1.txt文件 内容如下
Classfile /E:/accp/Y2/进阶内容/JVM/jvmTest/JvmTest/JVM_Project1/target/classes/com/zn/Test1.class Last modified 2020-3-10; size 563 bytes MD5 checksum 227f9972c01499bef690d9371d0b0e14 Compiled from "Test1.java" public class com.zn.Test1 minor version: 0 major version: 51 flags: ACC_PUBLIC, ACC_SUPER Constant pool: #1 = Methodref #5.#23 // java/lang/Object."<init>":()V #2 = Fieldref #24.#25 // java/lang/System.out:Ljava/io/PrintStream; #3 = Methodref #26.#27 // java/io/PrintStream.println:(I)V #4 = Class #28 // com/zn/Test1 #5 = Class #29 // java/lang/Object #6 = Utf8 <init> #7 = Utf8 ()V #8 = Utf8 Code #9 = Utf8 LineNumberTable #10 = Utf8 LocalVariableTable #11 = Utf8 this #12 = Utf8 Lcom/zn/Test1; #13 = Utf8 main #14 = Utf8 ([Ljava/lang/String;)V #15 = Utf8 args #16 = Utf8 [Ljava/lang/String; #17 = Utf8 a #18 = Utf8 I #19 = Utf8 b #20 = Utf8 c #21 = Utf8 SourceFile #22 = Utf8 Test1.java #23 = NameAndType #6:#7 // "<init>":()V #24 = Class #30 // java/lang/System #25 = NameAndType #31:#32 // out:Ljava/io/PrintStream; #26 = Class #33 // java/io/PrintStream #27 = NameAndType #34:#35 // println:(I)V #28 = Utf8 com/zn/Test1 #29 = Utf8 java/lang/Object #30 = Utf8 java/lang/System #31 = Utf8 out #32 = Utf8 Ljava/io/PrintStream; #33 = Utf8 java/io/PrintStream #34 = Utf8 println #35 = Utf8 (I)V { public com.zn.Test1(); descriptor: ()V flags: 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 3: 0 LocalVariableTable: Start Length Slot Name Signature 0 5 0 this Lcom/zn/Test1; public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: ACC_PUBLIC, ACC_STATIC Code: stack=2, locals=4, args_size=1 0: iconst_2 1: istore_1 2: iconst_5 3: istore_2 4: iload_2 5: iload_1 6: isub 7: istore_3 8: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream; 11: iload_3 12: invokevirtual #3 // Method java/io/PrintStream.println:(I)V 15: return LineNumberTable: line 5: 0 line 6: 2 line 7: 4 line 8: 8 line 9: 15 LocalVariableTable: Start Length Slot Name Signature 0 16 0 args [Ljava/lang/String; 2 14 1 a I 4 12 2 b I 8 8 3 c I } SourceFile: "Test1.java"
2、常量池
Constant Type Value 说明
3、描述符
3.1 字段描述符
3.2 方法描述符
4、解读方法字节码
public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V //方法描述,V表示该方法的返回值为void flags: ACC_PUBLIC, ACC_STATIC //方法修饰符,public,static的个数 Code: //stack=2,操作栈的大小为2,locals=4,本地变量表大小,args_size=1,参数的个数 stack=2, locals=4, args_size=1 0: iconst_2 //将数字2值压入擦作栈,位于栈的最上面 1: istore_1 //从操作栈中弹出一个元素(数字2),放入到本地变量表中,位于下标为1的位置(下标为0的是this) 2: iconst_5 //将数据5值压入操作栈,位于栈的最上面 3: istore_2 //操作栈中国弹出一个元素(5),放到本地变量表中,位于下标为2的位置 4: iload_2 //将本地变量表中下标为2的位置元素压入操作栈(5) 5: iload_1 //将本地变量表中下标为1的位置元素压入操作栈(2) 6: isub //操作栈中的2个数字相减 7: istore_3 8: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream; 通过#2号找到对应的常量,即可找到对应的引用 11: iload_3 12: invokevirtual #3 // Method java/io/PrintStream.println:(I)V 通过#3号找到对应的常量,即可找到对应的引用,进行方法调用 15: return LineNumberTable: line 5: 0 line 6: 2 line 7: 4 line 8: 8 line 9: 15 LocalVariableTable: //本地变量表 Start Length Slot Name Signature 0 16 0 args [Ljava/lang/String; 2 14 1 a I 4 12 2 b I 8 8 3 c I } SourceFile: "Test1.java"
4.1 图解
5、研究 i++ 与 ++i 的不同
i++表示,先返回再+1,++i表示,先+1再返回
5.1 编写测试代码
package com.zn; public class Test2 { public static void main(String[] args) { new Test2().method01(); new Test2().method02(); } public void method01(){ int i=1; int a=i++; System.out.println(a); } public void method02(){ int i=1; int a=++i; System.out.println(a); } }
执行成功target目录下便会生成class文件:
5.2 cmd 使用命令
javap -v Test2.class > Test2.txt
执行成功相应目录下生成Test2.txt文件:
5.3 查看class字节码
Classfile /E:/accp/Y2/进阶内容/JVM/jvmTest/JvmTest/JVM_Project1/target/classes/com/zn/Test2.class Last modified 2020-3-10; size 779 bytes MD5 checksum f811b140c108be80c28048c85c5f9963 Compiled from "Test2.java" public class com.zn.Test2 minor version: 0 major version: 51 flags: ACC_PUBLIC, ACC_SUPER Constant pool: #1 = Methodref #8.#27 // java/lang/Object."<init>":()V #2 = Class #28 // com/zn/Test2 #3 = Methodref #2.#27 // com/zn/Test2."<init>":()V #4 = Methodref #2.#29 // com/zn/Test2.method01:()V #5 = Methodref #2.#30 // com/zn/Test2.method02:()V #6 = Fieldref #31.#32 // java/lang/System.out:Ljava/io/PrintStream; #7 = Methodref #33.#34 // java/io/PrintStream.println:(I)V #8 = Class #35 // java/lang/Object #9 = Utf8 <init> #10 = Utf8 ()V #11 = Utf8 Code #12 = Utf8 LineNumberTable #13 = Utf8 LocalVariableTable #14 = Utf8 this #15 = Utf8 Lcom/zn/Test2; #16 = Utf8 main #17 = Utf8 ([Ljava/lang/String;)V #18 = Utf8 args #19 = Utf8 [Ljava/lang/String; #20 = Utf8 method01 #21 = Utf8 i #22 = Utf8 I #23 = Utf8 a #24 = Utf8 method02 #25 = Utf8 SourceFile #26 = Utf8 Test2.java #27 = NameAndType #9:#10 // "<init>":()V #28 = Utf8 com/zn/Test2 #29 = NameAndType #20:#10 // method01:()V #30 = NameAndType #24:#10 // method02:()V #31 = Class #36 // java/lang/System #32 = NameAndType #37:#38 // out:Ljava/io/PrintStream; #33 = Class #39 // java/io/PrintStream #34 = NameAndType #40:#41 // println:(I)V #35 = Utf8 java/lang/Object #36 = Utf8 java/lang/System #37 = Utf8 out #38 = Utf8 Ljava/io/PrintStream; #39 = Utf8 java/io/PrintStream #40 = Utf8 println #41 = Utf8 (I)V { public com.zn.Test2(); descriptor: ()V flags: 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 3: 0 LocalVariableTable: Start Length Slot Name Signature 0 5 0 this Lcom/zn/Test2; public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: ACC_PUBLIC, ACC_STATIC Code: stack=2, locals=1, args_size=1 0: new #2 // class com/zn/Test2 3: dup 4: invokespecial #3 // Method "<init>":()V 7: invokevirtual #4 // Method method01:()V 10: new #2 // class com/zn/Test2 13: dup 14: invokespecial #3 // Method "<init>":()V 17: invokevirtual #5 // Method method02:()V 20: return LineNumberTable: line 5: 0 line 6: 10 line 7: 20 LocalVariableTable: Start Length Slot Name Signature 0 21 0 args [Ljava/lang/String; public void method01(); descriptor: ()V flags: ACC_PUBLIC Code: stack=2, locals=3, args_size=1 0: iconst_1 1: istore_1 2: iload_1 3: iinc 1, 1 6: istore_2 7: getstatic #6 // Field java/lang/System.out:Ljava/io/PrintStream; 10: iload_2 11: invokevirtual #7 // Method java/io/PrintStream.println:(I)V 14: return LineNumberTable: line 9: 0 line 10: 2 line 11: 7 line 12: 14 LocalVariableTable: Start Length Slot Name Signature 0 15 0 this Lcom/zn/Test2; 2 13 1 i I 7 8 2 a I public void method02(); descriptor: ()V flags: ACC_PUBLIC Code: stack=2, locals=3, args_size=1 0: iconst_1 1: istore_1 2: iinc 1, 1 5: iload_1 6: istore_2 7: getstatic #6 // Field java/lang/System.out:Ljava/io/PrintStream; 10: iload_2 11: invokevirtual #7 // Method java/io/PrintStream.println:(I)V 14: return LineNumberTable: line 14: 0 line 15: 2 line 16: 7 line 17: 14 LocalVariableTable: Start Length Slot Name Signature 0 15 0 this Lcom/zn/Test2; 2 13 1 i I 7 8 2 a I } SourceFile: "Test2.java"
5.4 对比
i++:
public void method01(); descriptor: ()V flags: ACC_PUBLIC Code: stack=2, locals=3, args_size=1 0: iconst_1 //将数字1压入到操作栈 1: istore_1 //将数字1从操作栈弹出,压入到本地变量表中,下标为1 2: iload_1 //将本地变量表中获取下标为1的数据,压入到操作栈中 3: iinc 1, 1 //将本地变量中的1,在+1 6: istore_2 //将数字1从操作栈弹出,压入到本地变量表中,下标为2 7: getstatic #6 // Field java/lang/System.out:Ljava/io/PrintStream; 10: iload_2 //从本地变量表中获取下标为2的数据,压入到操作栈中 11: invokevirtual #7 // Method java/io/PrintStream.println:(I)V 14: return LineNumberTable: line 9: 0 line 10: 2 line 11: 7 line 12: 14 LocalVariableTable: Start Length Slot Name Signature 0 15 0 this Lcom/zn/Test2; 2 13 1 i I 7 8 2 a I
++i:
public void method02(); descriptor: ()V flags: ACC_PUBLIC Code: stack=2, locals=3, args_size=1 0: iconst_1 //将数字1压入到操作栈中 1: istore_1 //将数字1从操作栈弹出,压入到本地变量表中,下标为1 2: iinc 1, 1 //将本地变量中的1,在+1 5: iload_1 //从本地变量表中获取下标为1的数据,压入到操作栈中 6: istore_2 //将数据2从操作栈弹出,压入到本地变量表中,下标为2 7: getstatic #6 // Field java/lang/System.out:Ljava/io/PrintStream; 10: iload_2 //将本地变量表中获取下标为2的数据,压入到操作栈中 11: invokevirtual #7 // Method java/io/PrintStream.println:(I)V 14: return LineNumberTable: line 14: 0 line 15: 2 line 16: 7 line 17: 14 LocalVariableTable: Start Length Slot Name Signature 0 15 0 this Lcom/zn/Test2; 2 13 1 i I 7 8 2 a I
6、字符串拼接
6.1 编写测试代码
package com.zn; public class Test3 { public static void main(String[] args) { new Test3().m1(); new Test3().m2(); } public void m1() { String s1 = "123"; String s2 = "456"; String s3 = s1 + s2; System.out.println(s3); } public void m2() { String s1 = "123"; String s2 = "456"; StringBuilder sb = new StringBuilder(); sb.append(s1); sb.append(s2); String s3 = sb.toString(); System.out.println(s3); } }
执行成功target目录下便会生成class文件:
6.2 cmd 使用命令
javap -v Test3.class > Test3.txt
执行成功相应目录下生成Test3.txt文件:
6.3 查看class字节码
Classfile /E:/accp/Y2/进阶内容/JVM/jvmTest/JvmTest/JVM_Project1/target/classes/com/zn/Test3.class Last modified 2020-3-10; size 1098 bytes MD5 checksum aedb0fe86c340564b9e93a5281e3069a Compiled from "Test3.java" public class com.zn.Test3 minor version: 0 major version: 51 flags: ACC_PUBLIC, ACC_SUPER Constant pool: #1 = Methodref #14.#36 // java/lang/Object."<init>":()V #2 = Class #37 // com/zn/Test3 #3 = Methodref #2.#36 // com/zn/Test3."<init>":()V #4 = Methodref #2.#38 // com/zn/Test3.m1:()V #5 = Methodref #2.#39 // com/zn/Test3.m2:()V #6 = String #40 // 123 #7 = String #41 // 456 #8 = Class #42 // java/lang/StringBuilder #9 = Methodref #8.#36 // java/lang/StringBuilder."<init>":()V #10 = Methodref #8.#43 // java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; #11 = Methodref #8.#44 // java/lang/StringBuilder.toString:()Ljava/lang/String; #12 = Fieldref #45.#46 // java/lang/System.out:Ljava/io/PrintStream; #13 = Methodref #47.#48 // java/io/PrintStream.println:(Ljava/lang/String;)V #14 = Class #49 // java/lang/Object #15 = Utf8 <init> #16 = Utf8 ()V #17 = Utf8 Code #18 = Utf8 LineNumberTable #19 = Utf8 LocalVariableTable #20 = Utf8 this #21 = Utf8 Lcom/zn/Test3; #22 = Utf8 main #23 = Utf8 ([Ljava/lang/String;)V #24 = Utf8 args #25 = Utf8 [Ljava/lang/String; #26 = Utf8 m1 #27 = Utf8 s1 #28 = Utf8 Ljava/lang/String; #29 = Utf8 s2 #30 = Utf8 s3 #31 = Utf8 m2 #32 = Utf8 sb #33 = Utf8 Ljava/lang/StringBuilder; #34 = Utf8 SourceFile #35 = Utf8 Test3.java #36 = NameAndType #15:#16 // "<init>":()V #37 = Utf8 com/zn/Test3 #38 = NameAndType #26:#16 // m1:()V #39 = NameAndType #31:#16 // m2:()V #40 = Utf8 123 #41 = Utf8 456 #42 = Utf8 java/lang/StringBuilder #43 = NameAndType #50:#51 // append:(Ljava/lang/String;)Ljava/lang/StringBuilder; #44 = NameAndType #52:#53 // toString:()Ljava/lang/String; #45 = Class #54 // java/lang/System #46 = NameAndType #55:#56 // out:Ljava/io/PrintStream; #47 = Class #57 // java/io/PrintStream #48 = NameAndType #58:#59 // println:(Ljava/lang/String;)V #49 = Utf8 java/lang/Object #50 = Utf8 append #51 = Utf8 (Ljava/lang/String;)Ljava/lang/StringBuilder; #52 = Utf8 toString #53 = Utf8 ()Ljava/lang/String; #54 = Utf8 java/lang/System #55 = Utf8 out #56 = Utf8 Ljava/io/PrintStream; #57 = Utf8 java/io/PrintStream #58 = Utf8 println #59 = Utf8 (Ljava/lang/String;)V { public com.zn.Test3(); descriptor: ()V flags: 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 3: 0 LocalVariableTable: Start Length Slot Name Signature 0 5 0 this Lcom/zn/Test3; public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: ACC_PUBLIC, ACC_STATIC Code: stack=2, locals=1, args_size=1 0: new #2 // class com/zn/Test3 3: dup 4: invokespecial #3 // Method "<init>":()V 7: invokevirtual #4 // Method m1:()V 10: new #2 // class com/zn/Test3 13: dup 14: invokespecial #3 // Method "<init>":()V 17: invokevirtual #5 // Method m2:()V 20: return LineNumberTable: line 5: 0 line 6: 10 line 7: 20 LocalVariableTable: Start Length Slot Name Signature 0 21 0 args [Ljava/lang/String; public void m1(); descriptor: ()V flags: ACC_PUBLIC Code: stack=2, locals=4, args_size=1 0: ldc #6 // String 123 2: astore_1 3: ldc #7 // String 456 5: astore_2 6: new #8 // class java/lang/StringBuilder 9: dup 10: invokespecial #9 // Method java/lang/StringBuilder."<init>":()V 13: aload_1 14: invokevirtual #10 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 17: aload_2 18: invokevirtual #10 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 21: invokevirtual #11 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 24: astore_3 25: getstatic #12 // Field java/lang/System.out:Ljava/io/PrintStream; 28: aload_3 29: invokevirtual #13 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 32: return LineNumberTable: line 10: 0 line 11: 3 line 12: 6 line 13: 25 line 14: 32 LocalVariableTable: Start Length Slot Name Signature 0 33 0 this Lcom/zn/Test3; 3 30 1 s1 Ljava/lang/String; 6 27 2 s2 Ljava/lang/String; 25 8 3 s3 Ljava/lang/String; public void m2(); descriptor: ()V flags: ACC_PUBLIC Code: stack=2, locals=5, args_size=1 0: ldc #6 // String 123 2: astore_1 3: ldc #7 // String 456 5: astore_2 6: new #8 // class java/lang/StringBuilder 9: dup 10: invokespecial #9 // Method java/lang/StringBuilder."<init>":()V 13: astore_3 14: aload_3 15: aload_1 16: invokevirtual #10 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 19: pop 20: aload_3 21: aload_2 22: invokevirtual #10 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 25: pop 26: aload_3 27: invokevirtual #11 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 30: astore 4 32: getstatic #12 // Field java/lang/System.out:Ljava/io/PrintStream; 35: aload 4 37: invokevirtual #13 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 40: return LineNumberTable: line 17: 0 line 18: 3 line 19: 6 line 20: 14 line 21: 20 line 22: 26 line 23: 32 line 24: 40 LocalVariableTable: Start Length Slot Name Signature 0 41 0 this Lcom/zn/Test3; 3 38 1 s1 Ljava/lang/String; 6 35 2 s2 Ljava/lang/String; 14 27 3 sb Ljava/lang/StringBuilder; 32 9 4 s3 Ljava/lang/String; } SourceFile: "Test3.java"
从字节码中可以看出,m1()方法源码中是使用+好拼接,但是字节码中也被编译成了StringBuilder方式;
所以可以得出结论,字符串拼接,+号和StringBuilder是相等的,效率一样;
6.4 测试代码2
package com.zn; public class Test4 { public static void main(String[] args) { new Test4().m1(); new Test4().m2(); } public void m1() { String str = ""; for (int i = 0; i < 5; i++) { str = str + i; } System.out.println(str); } public void m2() { StringBuilder sb = new StringBuilder(); for (int i = 0; i < 5; i++) { sb.append(i); } System.out.println(sb.toString()); } }
6.5 生成txt查看字节码
javap -v Test4.class > Test4.txt
Classfile /E:/accp/Y2/进阶内容/JVM/jvmTest/JvmTest/JVM_Project1/target/classes/com/zn/Test4.class Last modified 2020-3-10; size 1176 bytes MD5 checksum dcc28dd685e81c8add6f9c826dd910a0 Compiled from "Test4.java" public class com.zn.Test4 minor version: 0 major version: 51 flags: ACC_PUBLIC, ACC_SUPER Constant pool: #1 = Methodref #14.#39 // java/lang/Object."<init>":()V #2 = Class #40 // com/zn/Test4 #3 = Methodref #2.#39 // com/zn/Test4."<init>":()V #4 = Methodref #2.#41 // com/zn/Test4.m1:()V #5 = Methodref #2.#42 // com/zn/Test4.m2:()V #6 = String #43 // #7 = Class #44 // java/lang/StringBuilder #8 = Methodref #7.#39 // java/lang/StringBuilder."<init>":()V #9 = Methodref #7.#45 // java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; #10 = Methodref #7.#46 // java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder; #11 = Methodref #7.#47 // java/lang/StringBuilder.toString:()Ljava/lang/String; #12 = Fieldref #48.#49 // java/lang/System.out:Ljava/io/PrintStream; #13 = Methodref #50.#51 // java/io/PrintStream.println:(Ljava/lang/String;)V #14 = Class #52 // java/lang/Object #15 = Utf8 <init> #16 = Utf8 ()V #17 = Utf8 Code #18 = Utf8 LineNumberTable #19 = Utf8 LocalVariableTable #20 = Utf8 this #21 = Utf8 Lcom/zn/Test4; #22 = Utf8 main #23 = Utf8 ([Ljava/lang/String;)V #24 = Utf8 args #25 = Utf8 [Ljava/lang/String; #26 = Utf8 m1 #27 = Utf8 i #28 = Utf8 I #29 = Utf8 str #30 = Utf8 Ljava/lang/String; #31 = Utf8 StackMapTable #32 = Class #53 // java/lang/String #33 = Utf8 m2 #34 = Utf8 sb #35 = Utf8 Ljava/lang/StringBuilder; #36 = Class #44 // java/lang/StringBuilder #37 = Utf8 SourceFile #38 = Utf8 Test4.java #39 = NameAndType #15:#16 // "<init>":()V #40 = Utf8 com/zn/Test4 #41 = NameAndType #26:#16 // m1:()V #42 = NameAndType #33:#16 // m2:()V #43 = Utf8 #44 = Utf8 java/lang/StringBuilder #45 = NameAndType #54:#55 // append:(Ljava/lang/String;)Ljava/lang/StringBuilder; #46 = NameAndType #54:#56 // append:(I)Ljava/lang/StringBuilder; #47 = NameAndType #57:#58 // toString:()Ljava/lang/String; #48 = Class #59 // java/lang/System #49 = NameAndType #60:#61 // out:Ljava/io/PrintStream; #50 = Class #62 // java/io/PrintStream #51 = NameAndType #63:#64 // println:(Ljava/lang/String;)V #52 = Utf8 java/lang/Object #53 = Utf8 java/lang/String #54 = Utf8 append #55 = Utf8 (Ljava/lang/String;)Ljava/lang/StringBuilder; #56 = Utf8 (I)Ljava/lang/StringBuilder; #57 = Utf8 toString #58 = Utf8 ()Ljava/lang/String; #59 = Utf8 java/lang/System #60 = Utf8 out #61 = Utf8 Ljava/io/PrintStream; #62 = Utf8 java/io/PrintStream #63 = Utf8 println #64 = Utf8 (Ljava/lang/String;)V { public com.zn.Test4(); descriptor: ()V flags: 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 3: 0 LocalVariableTable: Start Length Slot Name Signature 0 5 0 this Lcom/zn/Test4; public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: ACC_PUBLIC, ACC_STATIC Code: stack=2, locals=1, args_size=1 0: new #2 // class com/zn/Test4 3: dup 4: invokespecial #3 // Method "<init>":()V 7: invokevirtual #4 // Method m1:()V 10: new #2 // class com/zn/Test4 13: dup 14: invokespecial #3 // Method "<init>":()V 17: invokevirtual #5 // Method m2:()V 20: return LineNumberTable: line 5: 0 line 6: 10 line 7: 20 LocalVariableTable: Start Length Slot Name Signature 0 21 0 args [Ljava/lang/String; public void m1(); descriptor: ()V flags: ACC_PUBLIC Code: stack=2, locals=3, args_size=1 0: ldc #6 // String 2: astore_1 // 将空字符串压入到本地变量表中的下标为1的位置 3: iconst_0 // 将数字0压入操作栈顶 4: istore_2 // 将栈顶数字0压入到本地变量表中的下标为2的位置 5: iload_2 // 将本地变量中下标为2的数字0压入操作栈顶 6: iconst_5 // 将数字5压入操作栈顶 7: if_icmpge 35 //比较栈顶两int型数值大小,当结果大于等于0时跳 转到35 10: new #7 // class java/lang/StringBuilder 13: dup //复制栈顶数值并将复制值压入栈顶(数字5) 14: invokespecial #8 // Method java/lang/StringBuilder."<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/StringBuilder.append:(I)Ljava/lang/StringBuilder; 25: invokevirtual #11 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 28: astore_1 29: iinc 2, 1 32: goto 5 35: getstatic #12 // Field java/lang/System.out:Ljava/io/PrintStream; 38: aload_1 39: invokevirtual #13 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 42: return LineNumberTable: line 10: 0 line 11: 3 line 12: 10 line 11: 29 line 14: 35 line 15: 42 LocalVariableTable: Start Length Slot Name Signature 5 30 2 i I 0 43 0 this Lcom/zn/Test4; 3 40 1 str Ljava/lang/String; StackMapTable: number_of_entries = 2 frame_type = 253 /* append */ offset_delta = 5 locals = [ class java/lang/String, int ] frame_type = 250 /* chop */ offset_delta = 29 public void m2(); descriptor: ()V flags: ACC_PUBLIC Code: stack=2, locals=3, args_size=1 0: new #7 // class java/lang/StringBuilder 3: dup 4: invokespecial #8 // Method java/lang/StringBuilder."<init>":()V 7: astore_1 8: iconst_0 9: istore_2 10: iload_2 11: iconst_5 12: if_icmpge 27 15: aload_1 16: iload_2 17: invokevirtual #10 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder; 20: pop 21: iinc 2, 1 24: goto 10 27: getstatic #12 // Field java/lang/System.out:Ljava/io/PrintStream; 30: aload_1 31: invokevirtual #11 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 34: invokevirtual #13 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 37: return LineNumberTable: line 18: 0 line 19: 8 line 20: 15 line 19: 21 line 22: 27 line 23: 37 LocalVariableTable: Start Length Slot Name Signature 10 17 2 i I 0 38 0 this Lcom/zn/Test4; 8 30 1 sb Ljava/lang/StringBuilder; StackMapTable: number_of_entries = 2 frame_type = 253 /* append */ offset_delta = 10 locals = [ class java/lang/StringBuilder, int ] frame_type = 250 /* chop */ offset_delta = 16 } SourceFile: "Test4.java"