阿里P7移动互联网架构师进阶视频(每日更新中)免费学习请点击:https://space.bilibili.com/474380680
本篇文章将先从热修复原理来介绍热修复设计:java
在Android的热修复中主要用来替换类,资源,so的过程;android
Java 虚拟机git
栈架构指令集的主要缺点是执行速度相对来讲稍微慢一些;基于堆栈的机器须要更多指令,(内存)数组
Android 虚拟机缓存
而基于寄存器(硬件在CPU内部)的机器指令更长架构
速度: CPU - > 寄存器 -> 内存 -> 外存app
http://blog.csdn.net/ljtyzhr/article/details/39859659性能
Android 目前有2中虚拟机, Dalvik 和 ART 虚拟机;学习
Android 热修复其实主要是针对 Android 虚拟机加载类的一个过程,因此首先先咱们应该知道 Android 经常使用的虚拟机是 Dalvik 虚拟和 ART 虚拟机;优化
Android 4.0 以前是主要是的 Dalvik 虚拟机。 Android 4.4 以后开始支持 ART 虚拟机(可选), Android 5.0 以后就是 ART 虚拟机;
Dalvik 虚拟机在 Android 2.2 的时候引入了 JIT (Just in time), 也就是一边运行,一边编译成机器码在运行;这种编译成机器码的过程在应用重启的时候须要从新编译成机器码再运行,有点浪费性能(不是持久化),重复翻译,编译,运行;
在 Android 5.0 以后就使用彻底使用 ART 虚拟机;由于在 AOT (ahead of time) 的操做在安装的时候把 dex 优化成odex; 在Android N (7) 以前是全量dex 优化成 odex, 这样致使安装 apk 的时候,或者系统更新重启的时候很是耗时,特别的慢;
因此在 Android N 后引入了 JIT 和 AOT 的混合模式; 能够理解为“全时段的编译”(All-Of-the-Time compilation, 也叫 AOT;是否是发现有2个 AOT, 一开始我也很懵逼的;其实和Android 5.0 中的 AOT 是不太同样的;还有要注意的是Android N 以后的 JIT 和 Davlik 虚拟机中的JIT是不同的,简单理解就是高级版的JIT;这个高级版本的 JIT 过程会把处理后的odex缓存到 base.art (有些地方也叫 image ) 中;等下次app启动的时候,就先直接把这个优化后的 base.art 加载到内存中;这样就不会重复的 JIT了;
ART 初期是使用全量的 AOT (aheader of time) 变成机器码(指令); 由于耗安装时间和系统升级后的启动时间;因此在 ART 的时候,先把dex 解释成中间态的,不编译成机器码。在运行的时候,或者充电的时候,只编译“热代码”
引用infoq 的一篇文章 http://www.infoq.com/cn/news/2016/04/android-n-aot-jit
Android N(7.x)开发者预览版包含了一个混合模式的运行时。应用在安装时不作编译,而是解释字节码,因此能够快速启动。ART中有一种新的、更快的解释器,经过一种新的JIT完成,可是这种JIT的信息不是持久化的。取而代之的是,代码在执行期间被分析,分析结果保存起来。而后,当设备空转和充电的时候,ART会执行针对“热代码”进行的基于分析的编译,其余代码不作编译。为了获得更优的代码,ART采用了几种技巧包括深度内联。
对同一个应用能够编译数次,或者找到变“热”的代码路径或者对已经编译的代码进行新的优化,这取决于分析器在随后的执行中的分析数据。这个步骤仍被简称为AOT,能够理解为“全时段的编译”(All-Of-the-Time compilation)。
主要过程: java - (dex, class) - opt/oat -- odex;
Davlik 虚拟机: java - dex - opt -- D 类型的 odex (优化事后的仍是须要翻译); JIT
ART虚拟机: java -- dex -- oat -- A 类型的 odex (机器码类型文件); AOT ( Ahead of time)
混合模式: java -- dex -- oat -- (D类型的 odex, base.art: 热缓存,image) JIT(高级的JIT); AOT (All-Of-the-Time compilation)能够理解为“全时段的编译” ,profile
注意以上的 A 类型 odex 和 D 类型的 odex,只是用来代码 2 种是不一样的 odex,便于理解;
补丁包主要有 class, 资源文件,so的改动;
本文主要诉说类加载器的方案;
由于 Android 有 2 款虚拟机,因此应该针对 2 款虚拟机加载过程进行分析和处理;
Android 在编译的时候有个 65536 (2的16次方)问题。受限于Dlv 虚拟机的限制;不仅是方法名有限制,其实字段也是有限制的;
CLASS_ISPREVERIFIED 这个标记被打上的原理是,只要一个类里面和这个类的依赖都在一个dex中,那么这些类就被打上 PREVERIFIED 的标记;
单独有个[特殊的.dex]这个 dex 里面只有一个类,且其余的dex中的类都引用一下这个单独 dex 里面的类,那么,项目中全部的类,就不会被打上 CLASS_ISPREVERIFIED 这个标记
referrer->pDvmDex != resClassCheck->pDvmDex
补丁类和引用类应该在同一个dex里面;
fromUnverifiedConstant hook 使用 native 方式
类收到了类加载请求,他首先不会尝试本身去加载这个类,而是把这个请求委派给父类去完成,每个层次类加载器都是如此,所以全部的加载请求都应该传送到启动类加载其中,只有当父类加载器反馈本身没法完成这个请求的时候(在它的加载路径下没有找到所需加载的Class),子类加载器才会尝试本身去加载
相关日志
原文连接:https://my.oschina.net/jiemachina/blog/1587762
阿里P7移动互联网架构师进阶视频(每日更新中)免费学习请点击:https://space.bilibili.com/474380680