当前位置 博文首页 > 外星喵的博客:通过jvm指令手册看懂java反汇编源码

    外星喵的博客:通过jvm指令手册看懂java反汇编源码

    作者:[db:作者] 时间:2021-07-12 15:42

    1. 栈和局部变量操作

    1.1 将常量压入栈的指令

    指令功能描述
    aconst_null将null对象引用压入栈
    iconst_m1将int类型常量-1压入栈
    iconst_0将int类型常量0压入栈
    iconst_1将int类型常量1压入栈
    iconst_2将int类型常量2压入栈
    iconst_3将int类型常量3压入栈
    iconst_4将int类型常量4压入栈
    iconst_5将int类型常量5压入栈
    lconst_0将long类型常量0压入栈
    lconst_1将long类型常量1压入栈
    fconst_0将float类型常量0压入栈
    fconst_1将float类型常量1压入栈
    dconst_0将double类型常量0压入栈
    dconst_1将double类型常量1压入栈
    bipush将一个8位带符号整数压入栈
    sipush将16位带符号整数压入栈
    ldc把常量池中的项压入栈
    ldc_w把常量池中的项压入栈(使用宽索引)
    ldc2_w把常量池中long类型或者double类型的项压入栈(使用宽索引)

    1.2 从栈中的局部变量中装载值的指令

    指令功能描述
    iload从局部变量中装载int类型值
    lload从局部变量中装载long类型值
    fload从局部变量中装载float类型值
    dload从局部变量中装载double类型值
    aload从局部变量中装载引用类型值(refernce)
    iload_0从局部变量0中装载int类型值
    iload_1从局部变量1中装载int类型值
    iload_2从局部变量2中装载int类型值
    iload_3从局部变量3中装载int类型值
    lload_0从局部变量0中装载long类型值
    lload_1从局部变量1中装载long类型值
    lload_2从局部变量2中装载long类型值
    lload_3从局部变量3中装载long类型值
    fload_0从局部变量0中装载float类型值
    fload_1从局部变量1中装载float类型值
    fload_2从局部变量2中装载float类型值
    fload_3从局部变量3中装载float类型值
    dload_0从局部变量0中装载double类型值
    dload_1从局部变量1中装载double类型值
    dload_2从局部变量2中装载double类型值
    dload_3从局部变量3中装载double类型值
    aload_0从局部变量0中装载引用类型值
    aload_1从局部变量1中装载引用类型值
    aload_2从局部变量2中装载引用类型值
    aload_3从局部变量3中装载引用类型值
    iaload从数组中装载int类型值
    laload从数组中装载long类型值
    faload从数组中装载float类型值
    daload从数组中装载double类型值
    aaload从数组中装载引用类型值
    baload从数组中装载byte类型或boolean类型值
    caload从数组中装载char类型值
    saload从数组中装载short类型值

    1.3 将栈中的值存入局部变量的指令

    指令功能描述
    istore将int类型值存入局部变量
    lstore将long类型值存入局部变量
    fstore将float类型值存入局部变量
    dstore将double类型值存入局部变量
    astore将将引用类型或returnAddress类型值存入局部变量
    istore_0将int类型值存入局部变量0
    istore_1将int类型值存入局部变量1
    istore_2将int类型值存入局部变量2
    istore_3将int类型值存入局部变量3
    lstore_0将long类型值存入局部变量0
    lstore_1将long类型值存入局部变量1
    lstore_2将long类型值存入局部变量2
    lstore_3将long类型值存入局部变量3
    fstore_0将float类型值存入局部变量0
    fstore_1将float类型值存入局部变量1
    fstore_2将float类型值存入局部变量2
    fstore_3将float类型值存入局部变量3
    dstore_0将double类型值存入局部变量0
    dstore_1将double类型值存入局部变量1
    dstore_2将double类型值存入局部变量2
    dstore_3将double类型值存入局部变量3
    astore_0将引用类型或returnAddress类型值存入局部变量0
    astore_1将引用类型或returnAddress类型值存入局部变量1
    astore_2将引用类型或returnAddress类型值存入局部变量2
    astore_3将引用类型或returnAddress类型值存入局部变量3
    iastore将int类型值存入数组中
    lastore将long类型值存入数组中
    fastore将float类型值存入数组中
    dastore将double类型值存入数组中
    aastore将引用类型值存入数组中
    bastore将byte类型或者boolean类型值存入数组中
    castore将char类型值存入数组中
    sastore将short类型值存入数组中
    wide指令
    wide使用附加字节扩展局部变量索引

    1.4 通用(无类型)栈操作

    指令功能描述
    nop不做任何操作
    pop弹出栈顶端一个字长的内容
    pop2弹出栈顶端两个字长的内容
    dup复制栈顶部一个字长内容
    dup_x1复制栈顶部一个字长的内容,然后将复制内容及原来弹出的两个字长的内容压入栈
    dup_x2复制栈顶部一个字长的内容,然后将复制内容及原来弹出的三个字长的内容压入栈
    dup2复制栈顶部两个字长内容
    dup2_x1复制栈顶部两个字长的内容,然后将复制内容及原来弹出的三个字长的内容压入栈
    dup2_x2复制栈顶部两个字长的内容,然后将复制内容及原来弹出的四个字长的内容压入栈
    swap交换栈顶部两个字长内容

    2. 类型转换

    指令功能描述
    i2l把int类型的数据转化为long类型
    i2f把int类型的数据转化为float类型
    i2d把int类型的数据转化为double类型
    l2i把long类型的数据转化为int类型
    l2f把long类型的数据转化为float类型
    l2d把long类型的数据转化为double类型
    f2i把float类型的数据转化为int类型
    f2l把float类型的数据转化为long类型
    f2d把float类型的数据转化为double类型
    d2i把double类型的数据转化为int类型
    d2l把double类型的数据转化为long类型
    d2f把double类型的数据转化为float类型
    i2b把int类型的数据转化为byte类型
    i2c把int类型的数据转化为char类型
    i2s把int类型的数据转化为short类型

    3. 整数运算

    指令功能描述
    iadd执行int类型的加法
    ladd执行long类型的加法
    isub执行int类型的减法
    lsub执行long类型的减法
    imul执行int类型的乘法
    lmul执行long类型的乘法
    idiv执行int类型的除法
    ldiv执行long类型的除法
    irem计算int类型除法的余数
    lrem计算long类型除法的余数
    ineg对一个int类型值进行取反操作
    lneg对一个long类型值进行取反操作
    iinc把一个常量值加到一个int类型的局部变量上

    4. 逻辑运算

    4.1 移位操作

    指令功能描述
    ishl执行int类型的向左移位操作
    lshl执行long类型的向左移位操作
    ishr执行int类型的向右移位操作
    lshr执行long类型的向右移位操作
    iushr执行int类型的向右逻辑移位操作
    lushr执行long类型的向右逻辑移位操作

    4.2 按位布尔运算

    指令功能描述
    iand对int类型值进行“逻辑与”操作
    land对long类型值进行“逻辑与”操作
    ior对int类型值进行“逻辑或”操作
    lor对long类型值进行“逻辑或”操作
    ixor对int类型值进行“逻辑异或”操作
    lxor对long类型值进行“逻辑异或”操作

    4.3 浮点运算

    指令功能描述
    fadd执行float类型的加法
    dadd执行double类型的加法
    fsub执行float类型的减法
    dsub执行double类型的减法
    fmul执行float类型的乘法
    dmul执行double类型的乘法
    fdiv执行float类型的除法
    ddiv执行double类型的除法
    frem计算float类型除法的余数
    drem计算double类型除法的余数
    fneg将一个float类型的数值取反
    dneg将一个double类型的数值取反

    5. 对象和数组

    指令功能描述

    5.1 对象操作指令

    指令功能描述
    new创建一个新对象
    checkcast确定对象为所给定的类型
    getfield从对象中获取字段
    putfield设置对象中字段的值
    getstatic从类中获取静态字段
    putstatic设置类中静态字段的值
    instanceof判断对象是否为给定的类型

    5.2 数组操作指令

    指令功能描述
    newarray分配数据成员类型为基本上数据类型的新数组
    anewarray分配数据成员类型为引用类型的新数组
    arraylength获取数组长度
    multianewarray分配新的多维数组

    6. 控制流

    指令功能描述

    6.1 条件分支指令

    指令功能描述
    ifeq如果等于0,则跳转
    ifne如果不等于0,则跳转
    iflt如果小于0,则跳转
    ifge如果大于等于0,则跳转
    ifgt如果大于0,则跳转
    ifle如果小于等于0,则跳转
    if_icmpcq如果两个int值相等,则跳转
    if_icmpne如果两个int类型值不相等,则跳转
    if_icmplt如果一个int类型值小于另外一个int类型值,则跳转
    if_icmpge如果一个int类型值大于或者等于另外一个int类型值,则跳转
    if_icmpgt如果一个int类型值大于另外一个int类型值,则跳转
    if_icmple如果一个int类型值小于或者等于另外一个int类型值,则跳转
    ifnull如果等于null,则跳转
    ifnonnull如果不等于null,则跳转
    if_acmpeq如果两个对象引用相等,则跳转
    if_acmpnc如果两个对象引用不相等,则跳转

    6.2 比较指令

    指令功能描述
    lcmp比较long类型值
    fcmpl比较float类型值(当遇到NaN时,返回-1)
    fcmpg比较float类型值(当遇到NaN时,返回1)
    dcmpl比较double类型值(当遇到NaN时,返回-1)
    dcmpg比较double类型值(当遇到NaN时,返回1)

    6.3 无条件转移指令

    指令功能描述
    goto无条件跳转
    goto_w无条件跳转(宽索引)

    6.4 表跳转指令

    指令功能描述
    tableswitch通过索引访问跳转表,并跳转
    lookupswitch通过键值匹配访问跳转表,并执行跳转操作

    6.5 异常

    指令功能描述
    athrow抛出异常或错误
    finally子句
    jsr跳转到子例程
    jsr_w跳转到子例程(宽索引)
    rct从子例程返回

    7. 方法调用与返回

    7.1 方法调用指令

    指令功能描述
    invokcvirtual运行时按照对象的类来调用实例方法
    invokespecial根据编译时类型来调用实例方法
    invokestatic调用类(静态)方法
    invokcinterface调用接口方法

    7.2 方法返回指令

    指令功能描述
    ireturn从方法中返回int类型的数据
    lreturn从方法中返回long类型的数据
    freturn从方法中返回float类型的数据
    dreturn从方法中返回double类型的数据
    areturn从方法中返回引用类型的数据
    return从方法中返回,返回值为void

    7.3 线程同步

    指令功能描述
    montiorenter进入并获取对象监视器
    monitorexit释放并退出对象监视器

    如何根据以上指令手册翻译java源码呢?

    首先新建一个java类,这里用DemoForJavap.java举个例,源码如下:

    package com.example.demo;
    
    public class DemoForJavap{
    
    	public int add(){
    		int a = 1;
    		int b = 2;
    		int c = a+b;
    		return c;
    	}
    
    }
    

    使用javac命令编译成class文件后用javap -c命令进行反汇编

    在这里插入图片描述
    我们主要解读下add这个方法中的汇编码:

      public int add();
        Code:
           0: iconst_1      //将int类型常量1压入操作数栈
           1: istore_1		//将int类型值存入局部变量1,此处相当于int a=1;执行完毕
           2: iconst_2		//将int类型常量2压入操作数栈
           3: istore_2		//将int类型值存入局部变量2,此处相当于int b=2;执行完毕
           4: iload_1		//从局部变量1中装载int类型值
           5: iload_2		//从局部变量2中装载int类型值
           6: iadd			//执行int类型的加法
           7: istore_3		//将int类型值存入局部变量3,此处相当于int c=a+b;执行完毕
           8: iload_3		//从局部变量3中装载int类型值
           9: ireturn		//从方法中返回int类型的数据,此处相当于return c;执行完毕
    
    cs
    下一篇:没有了