Android进阶宝典 --- AndFix热修复原理解析

当我们写了一个方法,那么这个方法是如何被执行的呢?

public int add(){
   
    int a = 10;
    int b = 20;
    return a + b;
}

其实方法的本质就是arm指令,然后JVM的执行引擎会执行arm指令
在这里插入图片描述
add方法是java代码,java代码编译成class文件,还需要一步转换为dex文件,才能被Android虚拟机执行,arm指令是存在于dex文件中的,也就是说,我们可以从dex文件中取出arm指令,查看一个方式是如何被执行的

1 arm指令集

dx --dex --verbose --dump-to=dex_method.txt --dump-method=Method.add --verbose-dump Method.class 

Android中可以通过dx命令将class文件转换为dex文件,dx.bat位于Android SDK中的build-tools文件夹下,那么可以通过dx命令将class文件翻译成arm指令集
在这里插入图片描述
我看可以看一下,打印输出的arm指令集,Android虚拟机执行某个方法的时候,执行的就是这个指令集,这种指令集在加载的时候,存在JVM虚拟机的方法区中
在这里插入图片描述
执行的时候,JVM的执行引擎会将arm指令从方法区中拿出来,放到虚拟机栈中执行(栈帧的概念,每一个方法对应的dx指令集就是一个栈帧,每一次方法调用都有栈帧入栈和出栈)

关注点回到指令集上,在每一行指令前有一个数字,代表程序计数器记录的行号,精简之后的指令集(只保留每个行号的最后一个)

Method.add:()I:
regs: 0002; ins: 0001; outs: 0000
 
  0000: const/16 v0, #int 30 // #001e
  0002: return v0
  0003: code-address
  debug info
    line_start: 4
    parameters_size: 0000
    0000: prologue end
    0000: line 4
    0000: line 6
    end sequence
  source file: "Method.java"

另外还有一种方式获取字节码,是通过javap获取,这种跟dex指令有啥区别呢?其实都是字节码,但是javap获取的字节码是JVM执行的字节码,Android虚拟机是Dalvik或者Art虚拟机,执行的是dx指令集

public int add();
    descriptor: ()I
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=3, args_size=1
         0: bipush        10
         2: istore_1
         3: bipush        20
         5: istore_2
         6: iload_2
         7: iload_1
         8: idiv
         9: ireturn
      LineNumberTable:
        line 4: 0
        line 5: 3
        line 6: 6

这两者有什么区别呢?我们看同是执行 10 + 20 ,JVM是先创建一个10变量,然后再创建20 ,最后将两个相加然后返回;但是dx指令是直接计算好了,然后创建v0 = 30,直接返回,所以:Android编译器在编译的过程中会做优化,提高执行的效率

当一个class类加载进来之后,class类中有方法、成员变量等,这些类的信息加载的时候是放在方法区,当Java层调用某个方法时,执行引擎从方法区拿出dx指令集,作为栈帧拷贝到虚拟机栈(高速缓存区),CPU去读取每行指令,程序计数器+1,等到方法执行完毕,栈帧出栈。

2 AndFix热修复原理

之前我们介绍过阿里的AndFix或者Sophix是通过hook native层修改字节码指令完成,之前我们介绍的arm指令集,就是实现热修复的基础。

Method.add:()I:
regs: 0002; ins: 0001; outs: 0000
 
  0000: const/16 v0, #int 30 // #001e
  0002: return v0
  0003: code-address
  debug info
    line_start: 4
    parameters_size: 0000
    0000: prologue end
    0000: line 4
    0000: line 6
    end sequence
  source file: "Method.java"
public class Method {
   

    public int add(){
   
        int a = 10;
        int b = 20;
        return b / a;
    }
}
//调用
Method method = new Method
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Awesome_lay

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值