热修复部分原理和问题
2017.2.1 更
年前经过研究,腾讯的开源Tinker 更强大和配置简单,并且有专门的网站管理分发更新差异包,并且有微信作为实践,适用性高。(逃
----------------------------------------------分割线-----------------------------------------------
2016.11.11 更
偷了一张图: 开源的热更新挺稳定的 手机QQ目前所用的 [RocooFix] 原理
(https://github.com/dodola/RocooFix/tree/master/app)
----------------------------------------------分割线-----------------------------------------------
详细的教程(倾向于原理)
倾向于使用教程
** Numa 傻瓜式修复 **
1.dex分包:
编译失败,
android 2.3之前无法安装,dex文件过大(系统只分配了5M)
解决办法:分成两个dex,第二dex以资源形式存在,在Application的onCreate中注入。
2.分包原理 DexClassLoader 和 PathClassLoader。
pathList 查找, dexElement 保存dex数组。
遍历dexElements. 通常数组只有一个元素,apk安装包的classes.dex. 通过反射强行将dex文件添加到此 dexElements中.
3.热补丁修复技术的原理。
如果两个dex中存在相同的class文件会怎样?
先从第一个dex中找,找到了直接返回,遍历结束。而第二个dex中的class永远不会被加载进来。
简而言之,两个dex中存在相同class的情况下,dex1的class会覆盖dex2的class。
4.加载补丁原理:
dex保存在这个位置 BaseDexClassLoader–>pathList–>dexElements
1.apk的classes.dex可以从应用本身的DexClassLoader中获取。
2.patch_dex(补丁)的dex需要new一个DexClassLoader加载后在获取。(先加载)
3.分别通过反射获取dex文件,重新合并成一个数组,然后赋值给本身的ClassLoader的dexElements
5.CLASS_ISPRREVERIFIED问题:解决方法是在所有类的构造方法中添加System.out.println(AntilazyLoad.class);( 这个是个别打包在hark.dex中),
*1.不能在源码中直接加载,AntilazyLoad.class找不到,编译不通过。
*2.绕过编译,使用javassist操作字节码,直接注入代码。 Android Studio项目Gradle构建的,编译-打包-签名都是自动化的。
6.Gradle是通过一个一个Task执行完成整个流程的,其中肯定也有将所有class打包成dex的task。
在Gradle 1.5以上新出的 ** Transfrom ** Api。
- 1.5以下,想要在项目被打包成dex之前对class操作,需要创建一个Task,然后插入到dex之前,在自定义Task中使用javassist/asm对class进行操作 *
- 1.5以上,Transfrom 有自己的执行机制,不需要我们插入到task之前,Transfrom一经注册就会自动添加到Task执行序列中,并且是项目被打包成dex之前。
7.注册Transfrom : (一种解决方式. 坑较多。)
8.javassist使用: (太复杂 有时间去学)
9.Gradle: Gradle本身的领域对象主要有Project和Task,Project为Task提供执行上下文,所有的Plugin要向Project中添加用于配置的Property,要么向Project添加不同的Task,一个Task表示一个逻辑上较为独立的执行过程,比如编译Java源代码,拷贝文件,打包Jar文件,甚至可以是执行一个系统命令。
- Gradle可以看做是一个脚本,包含一系列的Task,依次执行这些task后,项目就打包成功了。
- Task通过inputs拿到一些东西,处理完毕之后就输出outputs,而下一个Task的inputs则是上一个Task的outputs。
- Plugin 为项目构建提供了Task,使用不同的plugin,module的功能也就不一样。