android热修复原理总结

背景

当app发布之后如果出现了紧急的线上bug,整个公司都会为此忙的焦头烂额,现公司如果线上出现严重的P1级bug,甚至大半夜整个项目组都得来紧急修复上线,而bug的原因可能仅仅是传错了参数,或者写错一行代码,而且修复后的app又得重新上架,直到用户更新后bug才会被修正。那热修复技术的出现就能很大程度上缓解这种情况,修复后不需要重新上架,用户也不需要重新下载安装。

原理

github上的热修复框架如nuwa,HotFix原理都是依据安卓App热补丁动态修复技术介绍Android dex分包方案
这两篇文章,我这里也只是对这两篇文章做一个自己的总结加深理解。
关于nuwa框架的使用看另一篇博客热修复框架nuwa的使用
热修复原理是基于Android的分包方案的,那么什么是Android的分包方案呢,Android2.3之前执行dexopt的内存只有5M,每个dex的方法数不能超过65535,当app功能复杂,类和方法特别多的时候就会在编译时报错。Android dex分包方案中的描述:

当一个app的功能越来越复杂,代码量越来越多,也许有一天便会突然遇到下列现象:

  1. 生成的apk在2.3以前的机器无法安装,提示INSTALL_FAILED_DEXOPT

  2. 方法数量过多,编译时出错,提示:

Conversion to Dalvik format failed:Unable to execute dex: method ID
not in [0, 0xffff]: 65536

出现这种问题的原因是:

  1. Android2.3及以前版本用来执行dexopt(用于优化dex文件)的内存只分配了5M

  2. 一个dex文件最多只支持65536个方法。

解决办法是将编译好的class文件打成两个dex的包,运行时注入ClassLoader。如何注入呢,先看一下Android的ClassLoader体系,图片是分包方案里扒的。
这里写图片描述
可以看到实现类有两个DexClassLoader和PathClassLoader,其中PathClassLoader是用来Android用来加载Android系统类和应用的加载器,DexClassLoader用来加载.dex和.jar中的class.dex文件。看一下BaseDexClassLoader加载类的方法,从pathList里根据类名找,找不到就class not found。pathList是BaseDexClassLoader中的一个对象,它包含一个dexElements集合,找类就是听过遍历这个集合,拿到dexFile去找类。

一个ClassLoader可以包含多个dex文件,每个dex文件是一个Element,多个dex文件排列成一个有序的数组dexElements,当找类的时候,会按顺序遍历dex文件,然后从当前遍历的dex文件中找类,如果找类则返回,如果找不到从下一个dex文件继续查找。(来自:安卓App热补丁动态修复技术介绍)

#BaseDexClassLoader
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
    Class clazz = pathList.findClass(name);

    if (clazz == null) {
        throw new ClassNotFoundException(name);
    }

    return clazz;
}

#DexPathList
public Class findClass(String name) {
    for (Element element : dexElements) {
        DexFile dex = element.dexFile;

        if (dex != null) {
            Class clazz = dex.loadClassBinaryName(name, definingContext);
            if (clazz != null) {
                return clazz;
            }
        }
    }

    return null;
}

#DexFile
public Class loadClassBinaryName(String name, ClassLoader loader) {
    return defineClass(name, loader, mCookie);
}
private native static Class defineClass(String name, ClassLoader loader, int cookie);

这样我们将有bug的类打成patch.jar然后插入到dexElements的最前边位置,findclass的时候就会从我们的patch.jar 中开始找,找到类之后就返回,有问题的类就被补丁包中的替换掉了。之后还有一个CLASS_ISPREVERIFIED的问题,详细可以看安卓App热补丁动态修复技术介绍主要是说,如果类和其引用类如果不在同一个dex包里就会报错,校检出这个错的前提是引用类被打上了CLASS_ISPREVERIFIED标识,这个标识是什么时候被打上的呢,在虚拟机启动的时候如果一个类的private,static,或者构造方法直接引用到的类都在同一个dex包里就会给当前类打上这个标识,所以要阻止这个表示被打上,我们要让类引用一个外部dex包里的类,往所有的类的构造函数中插入一段

if (ClassVerifier.PREVENT_VERIFY) {
    System.out.println(AntilazyLoad.class);
}
public class AntilazyLoad
{

}

所以我们还需要一个hack.dex,写个空的类AntilazyLoad打成dex包,而且必须先加载这个包,否则引用这个类的地方就会class not fount,加载方法就和之前的一样啦,要注意

Application作为应用的入口不能插入这段代码。(因为载入hack.dex的代码是在Application中onCreate中执行的,如果在Application的构造函数里面插入了这段代码,那么就是在hack.dex加载之前就使用该类,该类一次找不到,会被永远的打上找不到的标志)(来自:安卓App热补丁动态修复技术介绍)。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
----《深入探索Android修复技术原理》高清完整版PDF---- 2017年6月,阿里巴巴手淘技术团队推出了史上首个非侵入式移动更新解决方案——Sophix。在Android修复的三大领域:代码修复、资源修复、SO修复方面,以及方案的安全性和易用性方面,Sophix都做到了业界领先。 《深入探索Android修复技术原理》从阿里Sophix方案开发过程入手权威解读,分享了阿里巴巴手淘技术团队对系统底层的原创性发现,是业界首部全方位完整介绍修复原理的书籍。 阿里技术大牛联袂推荐 自 2014 年至今,手淘定义和引领了业界 Android 组件化和修复技术风潮,至于后来者 Instant App 或多或少也受了国内技术风气影响。今天看到团队同学将这块技术认真系统化整理成书,非常欣喜。在这本书里,既能看到对修复技术风潮的发展历史系统深入总结,看到国内程序员在Android系统级技术持续突破上的不懈努力,更看到国内程序员坚持打造世界级优秀专业移动技术产品的雄心壮志! 手机淘宝基础平台部负责人,阿里巴巴资深技术专家 吴天华(天施) 业内少有的讲解 Android 修复的深度书籍,对于原理、代码讲解得非常的清晰和深入,值得 Android 工程师研读。 手机淘资深专家,倪生华(玄黎) 应用修复是一项略带神秘而又颇具争议的技术,但是它的确赋予应用开发者“驾着飞机修引擎”的能力。本书从 Android 应用修复技术的原理及代码实现、多种方案进行比较的角度,系统化地阐述了 Android 平台上的应用修复技术。对 Android 应用修复有好奇心的技术人员,这本专题书不容错过。 计算机技术领域著名作家,阿里巴巴飞猪事业部首席架构师 潘爱民

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值