zoukankan      html  css  js  c++  java
  • 字节码查看与动态字节

    一.字节码查看

    将.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
    二.动态字节技术

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

    字节码操作类库:
    1.BCEL
    2.ASM:轻量级的Java字节码操作框架,SpringAOP底层基于ASM字节码技术
    3.CGLIB 基于ASM
    4.javassist

     三:i++和++i的区别

    public class Test2 {
        public static void main(String[] args) {
            new Test2().method1();
            new Test2().method2();
        }
    
        public void method1() {
             int i = 1;
            int a = i++;
            System.out.println(a);
            //打印1
        }
    
        public void method2() {
            int i = 1;
            int a = ++i;
            System.out.println(a);
            //打印2 
        }
    }

    字节码节选

    i++

     
        stack=2, locals=3, args_size=1
             0: iconst_1            //将int类型的1压入栈
             1: istore_1            //出栈一个变量放入局部变量表中下标为1的位置,下标为0的位置存放的是this指针,此时栈为空,    
             2: iload_1                //从局部变量表中取出下标为1(实际值此处为1)的变量压入操作数栈中
             3: iinc          1, 1    //将局部变量表中下标为1的变量进行加1操作
             6: istore_2            //出栈一个变量放入局部变量表中下标为2的位置,这一步没有对操作栈中的数进行操作,直接出栈到变量表中
             7: getstatic     #6       //去常量池中引用"#6"符号引用的类与方法                 // Field java/lang/System.out:Ljava/io/PrintStream;
            10: iload_2                //从局部变量表中取出下标为1(实际值此处为1)的变量压入操作数栈中
            11: invokevirtual #7       //执行println方法               // Method java/io/PrintStream.println:(I)V
            14: return
     

    ++i

     
          stack=2, locals=3, args_size=1
             0: iconst_1            //将int类型的1压入栈
             1: istore_1            //出栈一个变量放入局部变量表中下标为1的位置,下标为0的位置存放的是this指针,此时栈为空,    
             2: iinc          1, 1    //将局部变量表中下标为1的变量进行加1操作
             5: iload_1                //从局部变量表中取出下标为1(实际值此处为2)的变量压入操作数栈中
             6: istore_2            //出栈一个变量放入局部变量表中下标为2的位置,(实际值此处为2)
             7: getstatic     #6    //去常量池中引用"#6"符号引用的类与方法               // Field java/lang/System.out:Ljava/io/PrintStream;
            10: iload_2                //从局部变量表中取出下标为1(实际值此处为2)的变量压入操作数栈中
            11: invokevirtual #7    //执行println方法                 // Method java/io/PrintStream.println:(I)V
            14: return
     
     
    i++

    只是在本地变量中对数字做了相加,并没有将数据压入到操作栈

    将前面拿到的数字1,再次从操作栈中拿到,压入到本地变量中

    ++i

    将本地变量中的数字做了相加,并且将数据压入到操作栈

    将操作栈中的数据,再次压入到本地变量中 

     

     

  • 相关阅读:
    后端注册接口完善
    编写注册接口
    Git 多人开发及常见问题
    Git 常用命令
    GIT 的安装及配置SSH
    ORM查询方法(整理)
    HTTP的系列理解与整理
    Unity C# 反射
    C# 中的委托和事件
    Unity C# 运用 GetSaveFileName() 导出Excel文件
  • 原文地址:https://www.cnblogs.com/danxun/p/12463273.html
Copyright © 2011-2022 走看看