Android 热修复架构杂谈

1,296 阅读4分钟
原文链接: qbeenslee.com

与前后端相比, 移动端对热修复的需求更为迫切和复杂. iOS上已有JSPatch这套成熟并被官方默许的解决方案. 然而Android上的热修复方案的演进则曲折的多, 简述一下鄙人的心路历程.

Dexposed

github.com/alibaba/dex…

最早是在百川大会上听说这个方案, 但整个接入过程体验了一下真是吐了一口老血. 由于Dexposed不支持ART Runtime一开始就被放弃了.

Andfix

github.com/alibaba/and…

真正尝试接入的热修复方案. 刚开始有其他公司的基友说是测试几百台手机都没有问题(幼稚的我竟然相信了), 然后就开始研究Andfix.

Andfix是一个可以实时修复的方案, 修复范围是方法, 具体是通过native hook java的方法反射运行补丁包中相应的方法来进行修复.

尼玛, 随着使用与测试的深入发现了许多问题然后一个一个的去填掉, 到最后上线还是遇到一些机型进行修复造成crash后立马下线掉了(兼容性问题). 其中还碰到ART模式下两个补丁同时修复同一个类会crash.

下面是测试后得出Andfix的修复范围:

修复内容是否支持备注
修改方法(使用的代码中不引入新的类)
新增方法
跨版本修复版本名变化会删除差异包
添加新的域(成员变量)差异包编译不通过
添加新的类NoClassDefFoundError
在方法内添加新的内部类NoClassDefFoundError
修改内部类里的方法(看操作的地方的this是否指向内部类)NoClassDefFoundError
inline方法
参数超过8个或带有long,double或者float的方法

如有错误请给予指正

其实Andfix是一套比较完善的热修复方案, 里面有许多思路值得借鉴. 但是考虑到如果继续投入精力在Andfix上所耗费的成本具有很大的不确定性, 遂放弃了Andfix.

go die

Ps: 现在github上开源的Andfix已经差不多是KPI项目了, 阿里内部已经出第二个版本了, 而且内部人士表示不会开源. 如果有后来者想继续研究Andfix, 可以反编译支付宝Android端的代码学习借鉴一下.

PPs: 安利一个反编译工具 jadx

RocooFix

github.com/dodola/Roco…

某日老司机发我一链接, 叫我看看这个热修复方案, 遂开始研究RocooFix.

RocooFix是基于Qzone热修复方案的实践, 与之相似的还有Nuwa, HotFix. Qzone方案的修复范围Class级的替换(仅包括java文件, 不支持替换资源文件, so文件等), 而且需要在获取补丁后再次启动方可生效并影响app启动速度(如果项目已经分包就忽略这条), 插桩具有侵入性. 整个方案包括运行时工具和编译时工具, 运行时工具大致就是一套multidex框架, 编译时工具则主要是生成差异包和插桩.

RocooFix这套工具比较基础, 为了完善的热修复方案需要考虑到一些点:

整体运行架构如图:

framework

安全策略

想起微信团队对JSPatch安全处理方式是采用RSA签名验证, 并且Android发布release包的时候也是需要签名的. 所以何不利用Android keystore对补丁签名, 然后在下发时进行校验.

jspatch safe

为了方便我是直接修改RocooFix的gradle插件代码, 在生成补丁后通过SigningConfig获取本地keystore签名信息并使用jarsigner对补丁进行签名.

为了安全性, 实际使用中还采用了加密https来下发补丁文件.

管理逻辑

现在要实现的最优目标是无感知的将bug给修复掉, 当然也可以在接收到新补丁后弹框让用户选择强制重启(万不得以的时候).

为实现无感知的修复bug避免重启给用户造成的困惑, 实际中会监听App退到后台, 此时如果存在新的补丁的话kill掉进程. 判断应用处于后台我是采用ActivityLifecycleCallbacks (API level 14), 其他方案也可以参考AndroidProcess这个项目.

为了提高补丁的下发概率最好能配合推送服务.

Ps: 以上都不包括RocooFix中实时修复的部分.

Tinker

github.com/zzz40500/Ti…

还在研究中…