JVM是Oracle用来运行java代码的虚拟机,将code转成机器字节码。
Dalvik是Google设计的专门用来在android平台上运行的虚拟机。能运行.dex的java程序。.dex是专门用于在Dalvik上运行的一种压缩格式。在一台android机上,Dalvik会为每个程序单独开辟一个Linux进程,防止一个程序崩溃引起其他程序关闭。
由于每个app启动,都会有一个Dalvik虚拟机,所以同时开启很多app的时候,因为系统cpu、memory等资源的限制,必然会拖慢整个手机的速度。这也是为什么android跟不上ios速度的原因
在一个解释器上执行VM指令包含三个步骤:指令分派、访问操作数和执行计算
指令分派负责从内存中读取VM指令,然后跳转到相应的解释器代码指令分派中。Stack-based需要更多的指令。
访问操作数是指读取和写回-源操作数和目的操作数
dex字节码是将多个字节码集中在一起,这样就提高了虚拟机对他的访问速度和io效率。然后VM将字节码解释成机器码。那DVM每次执行app的时候都需要即使转换JIT,而ART(android runtime)机制则不同,第一次安装的时候字节码就转成机器码存在本地。这个过程叫AOT预编译Ahead-Of-Time
当一个apk在安装的时候,apk中的classes.dex会被虚拟机(dexopt)优化成odex文件,然后才会拿去执行

寄存器的本质,是runtime stack最顶端的随机访问区域。如果一个指令集允许对runtime stack的最顶端进行随机访问,这个系统就是基于寄存器的。如果一个指令集只允许对runtime stack的top-most的一两个entry进行访问,就是严格的基于栈的系统。
机器码,完全依附硬件而存在~并且不同硬件由于内嵌指令集不同,即使相同的0 1代码意思也可能是不同的~换句话说,根本不存在跨平台性~比如~不同型号的CPU,你给他个指令10001101,他们可能会解析为不同的结果~
我们知道JAVA是跨平台的,为什么呢?因为他有一个jvm,不论那种硬件,只要你装有jvm,那么他就认识这个JAVA字节码~~~~至于底层的机器码,咱不用管,有jvm搞定,他会把字节码再翻译成所在机器认识的机器码
热修复的原理也是如此:
一个ClassLoader可以包含多个dex文件,每个dex文件是一个Element,多个dex文件排列成一个有序的数组dexElements,当找类的时候,会按顺序遍历dex文件,然后从当前遍历的dex文件中找类,如果找类则返回,如果找不到从下一个dex文件继续查找。
// pathclassloader加载apk内部的dex文件,而dexclassloader可以加载外部的jar和dex文件,但是PathClassLoader和DexClassLoader都继承自BaseDexClassLoader。在BaseDexClassLoader中有如下源码:
public Class findClass(Stringname) {
for (Element element : dexElements) {
DexFile dex = element.dexFile;
if (dex != null) {
Class clazz =dex.loadClassBinaryName(name, definingContext);
if (clazz != null) {
return clazz;}}}
return null;}
也就是根据名字查找类名去每个dex查找类

如果一个dex中的某个类,在1.static方法 2.private方法 3.构造函数 4.override方法
中直接引用了其他dex中的类,那么该类不会被打上CLASS_ISPREVERIFIED标志。相反,如果是直接引用了同一个dex中的其他类,它将会被加载器打上标记。所以如果我们要在主app的dex中加载热修复dex中的类,就要避免响应类被打上标记。所以有人想出一个“聪明”的办法,在application的oncreate中加上一句话System.out.println(XXX.class),其中XXX是热修复dex中的类。但是有个问题就是,程序刚启动的时候,热修复patch.dex此时还未加载,所以本app会报错找不到该类.
接入前先了解2个类,因为主流的热修复都是同样的原理,让加载器替换掉部分dex文件
1,PathClassLoader:Android是使用这个类作为其系统类和应用类的加载器。并且对于这个类呢,只能去加载已经安装到Android系统中的apk文件
2,DexClassLoader:该类可以用来加载.jar和.apk类型的文件内部加载classes.dex文件。可以用来执行非安装的程序代码
其实在插件化的开发中,我们也是提供一个apk,让我们的app去加载这个apk,它也是通过DexClassLoader来加载的。一个ClassLoader可以包含多个dex文件(可能是apk,jar等格式),每个dex文件是一个Element,多个dex文件排列成一个有序的数组dexElements,当找类的时候,会按顺序遍历dex文件,然后从当前遍历的dex文件中找类,如果找类则返回,如果找不到从下一个dex文件继续查找。
我们知道,将apk解压之后,会看到一个classes.dex的文件,通过反编译工具最后发现它就是我们工程的code。我们安装好的app中,就是通过DexClassLoader.java类来加载这个dex文件的Dalvik
说了这么多都是为热修复做铺垫。热修复需要花点篇幅来说具体的操作,先附一张流程图吧,下次再写一篇热修复代码层的操作:

网友评论