JVM字节码解析

不问归期 提交于 2020-03-11 13:57:52

一.字节码查看
                将.java源文件编译成.class二进制字节码文件,运行该字节码文件
                
                1.将class字节码文件内容输出到文本文件当中
                    javap -v xxx.class > xxx.txt
                    
                    第一个部分:
                        显示生成class的java源文件的基本信息
                          Classfile /C:/Users/FLC/Desktop/授课内容/授课案例/Y2170/day22/jvm_project/jvm_day01/target/classes/com/wdksoft/ClassTest.class
                          Last modified 2020-3-11; size 585 bytes
                          MD5 checksum 39fa2636495e5b4bf08da6decc537381
                          Compiled from "ClassTest.java"
                          public class com.wdksoft.ClassTest
                          minor version: 0
                          major version: 51
                          flags: ACC_PUBLIC, ACC_SUPER
                    
                    第二个部分:显示该类所涉及到的常量池,共有35个常量
                        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/wdksoft/ClassTest
                           #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/wdksoft/ClassTest;
                          #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               ClassTest.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/wdksoft/ClassTest
                          #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.wdksoft.ClassTest();
                        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/wdksoft/ClassTest;
                    
                    第四部分:显示main方法的信息
                        public static void main(java.lang.String[]);
                            descriptor: ([Ljava/lang/String;)V                方法的描述,V代表返回值为void
                            flags: ACC_PUBLIC, ACC_STATIC                    方法修饰符 public  static
                            Code:
                              stack=2, locals=4, args_size=1                stack代表操作栈的大小   locals本地变量表大小    args_size代表参数个数
                                 0: iconst_2                                将数据2压入到操作栈当中,位于栈顶
                                 1: istore_1                                从操作栈当中弹出一个数据,放到本地变量表当中,下标为1,0是this,操作栈当中数据清空
                                 2: iconst_5                                将数据5压入到操作栈当中,位于栈顶
                                 3: istore_2                                从操作栈当中弹出一个数据,放到本地变量表当中,下标为2,0是this,操作栈当中数据清空
                                 4: iload_2                                    将本地变量表中的下标为2的数据压入到操作站
                                 5: iload_1                                    将本地变量表中的下标为1的数据压入到操作站
                                 6: isub                                    将操作栈中的两个数据相减
                                 7: istore_3                                将相减的结果压入到本地本地变量表当中,下标为3
                                 8: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
                                11: iload_3                                    将本地变量表中下标为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
                
   案例研究:

  1. 研究 i++ 与 ++i 的不同
      我们都知道,i++表示,先返回再+1,++i表示,先+1再返回。它的底层是怎么样的呢? 我们一起探究下。

       i++:

                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        


                  
                    ++i:

                0: iconst_1 //将数字1压入到操作栈
                1: istore_1 //将数字1从操作栈弹出,压入到本地变量表中,下标为1
                2: iinc 1, 1// 将本地变量中的1,再+1
                5: iload_1 //从本地变量表中获取下标为1的数据(2),压入到操作栈中
                6: istore_2 //将数字2从操作栈弹出,压入到本地变量表中,下标为2
                7: getstatic #6 // Field
                java/lang/System.out:Ljava/io/PrintStream;
                10: iload_2 //从本地变量表中获取下标为2的数据(2),压入到操作栈中
                11: invokevirtual #7 // Method
                java/io/PrintStream.println:(I)V
                14: return


                    区别:
                    i++
                    只是在本地变量中对数字做了相加,并没有将数据压入到操作栈
                    将前面拿到的数字1,再次从操作栈中拿到,压入到本地变量中
                    ++i
                    将本地变量中的数字做了相加,并且将数据压入到操作栈
                    将操作栈中的数据,再次压入到本地变量中

                
            二.动态字节码技术
                在程序运行或者编译时期,通过动态字节码技术对类新增,删除,修改类的内部结构,包括字段和方法
                动态字节码技术应用场景:AOP,Lombok,动态修改class文件等等

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!