==
好几个月之前关于Android App热补丁修复火了一把,源于QQ空间团队的一篇文章[安卓App热补丁动态修复技术介绍]((),然后各大厂的开源项目都出来了,本文的实践基于[HotFix]((),也就是QQ空间技术团队那篇文章所应用的技术,笔者会把整个过程的细节和思路在文章中详说,研究这个的出发点也是为了能紧急修复app的bug,而不需要重复发包,不需要用户重新下载app就能把问题解决,个人觉得这个还是蛮有价值的,虽然老板不知道….。
项目结构
====
这里笔者创建一个新的项目”HotFixDemo”,带大家一步一步来完成Hotfix这个框架实现,这个项目包含以下module:
- app :我们的Android应用程序Module。
- buildsrc :使用Groovy实现的项目,提供了一个类,用来实现修改class文件的操作。
- hackdex :提供了一个类,后面会用来打包成hack.dex,也是buildsrc里面实现在所有类的构造函数插入的一段代码所引用到的类。
- hotfixlib :这个module最终会被app关联,里面提供实现热补丁的核心方法
这个Demo里面的代码跟HotFix框架基本无异,主要是告诉大家它实现的过程,如果光看代码,不实践是无法把它应用到你自己的app上去的,因为有很多比较深入的知识需要你去理解。
先说原理
====
关于实现原理,QQ空间那篇文章已经说过了,这里我再重新阐述一遍:
- Android使用的是PathClassLoader作为其类的加载器
- 一个ClassLoader可以包含多个dex文件,每个dex文件是一个Element,多个dex排列成一个有序的dexElements数组
- 当找类的时候会遍历dexElements数组,从dex文件中找类,找到则返回,否则继续下一个dex文件查找
- 热补丁的方案,其实就是将有问题的类单独打包成一个dex文件(如:patch.dex),然后将这个dex插入到dexElements数组的最前面去。
ok,这个就是HotFix对app进行热补丁的原理,其实就是用ClassLoader加载机制,覆盖掉有问题的方法,然后我们所谓的补丁就是将有问题的类打成一个包。
再说问题
====
当然要实现热补丁动态修复不会很容易,我们首要解决的一个问题是:
当虚拟机启动时,当verify选项被打开时,如果static方法、private方法、构造函数等,其中的直接引用(第一层关系)到的类都在同一个dex文件中,那么该类会被打上CLASS_ISPREERIFIED标记
如下图所示: