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热补丁动态修复技术介绍)。

时间: 2024-10-09 04:29:47

android热修复原理总结的相关文章

Android热修复原理普及

Android热修复原理普及 这段时间比较难闲,就抽空研究一下Android热修复的原理.自从Android热修复这项技术出现之后,随之而现的是多种热修复方案的出现.前两天又看到一篇文章分析了几种热修复方案的比较. 原文地址是:[Android热修复] 技术方案的选型与验证 看完这篇文章,有点汗颜.有这么多的热修复方案,并且他们之间的实现原理也不一样,各有优缺点. 然后在尼古拉斯_赵四的博客中看到几篇关于热修复的文章,对着这几篇文章撸了一番.大概的了解了热修复一种原理,其思路和QQ空间提出的安卓

Android 热修复原理(主要谈代码修复)

Android开发中,热修复技术被越来越多的开发者使用,市面上也出现很多成熟的开源框架.但对大部分开发者来说,热修复依然是一个既熟悉又陌生的词.仅仅知道热修复的作用,会使用框架,那样意义并不大.我们还要知道热修复的原理,这样不管框架如何变化,只要基本原理不变,我们都可以快速掌握它,或者自己动手写一个适合项目的热修复框架. 热修复介绍 1.开发流程 当项目出现紧急bug时,传统的开发流程是发布新版本,引导用户覆盖安装.抛开平台审核上线的时间不说,一天重复下载安装至少两次的用户体验是很差的.而热修复

Android热修复原理

一. AndFix AndFix的原理就是方法的替换,把有bug的方法替换成补丁文件中的方法.注:在Native层使用指针替换的方式替换bug方法,已达到修复bug的目的. AndFix采用native hook的方式,这套方案直接使用dalvik_replaceMethod替换class中方法的实现.由于它并没有整体替换class, 而field在class中的相对地址在class加载时已确定,所以AndFix无法支持新增或者删除filed的情况(通过替换init与clinit只可以修改fie

聊聊Android 热修复Nuwa有哪些坑

原创地址:http://blog.csdn.net/sbsujjbcy/article/details/51028027 前面写了两篇关于Nuwa的文章 Android 热修复Nuwa的原理及Gradle插件源码解析 Android 热修复使用Gradle Plugin1.5改造Nuwa插件 然后我说了Nuwa有坑,有人就问Nuwa到底有哪些坑,这篇文章对自己在Nuwa上走过的坑做一个总结,如果你遇到了其他坑,欢迎留言,我会统一加到文章中去.当然有些也不算是Nuwa的坑,算是ClassLoade

Android热修复:Andfix和Hotfix,两种方案的比较与实现

Andfix和hotfix是两种android热修复框架. android的热修复技术我看的最早的应该是QQ空间团队的解决方案,后来真正需要了,才仔细调查,现在的方案中,阿里有两种Dexposed和Andfix框架,由于前一种不支持5.0以上android系统,所以阿里系的方案我们就看Andfix就好.Hotfix框架算是对上文提到的QQ空间团队理论实现.本文旨在写实现方案,捎带原理. Andfix 引入 框架官网:https://github.com/alibaba/AndFix 介绍是用英文

Android 热修复方案分析

绝大部分的APP项目其实都需要一个动态化方案,来应对线上紧急bug修复发新版本的高成本.之前有利用加壳,分拆两个dex结合DexClassLoader实现了一套全量更新的热更方案.实现原理在Android 基于Proxy/Delegate 实现bug热修复这篇博客中有分解.因为这套方案是在Java端实现,并且是全量更新所以兼容性较好,成功率较高.但是在线上跑了几个月之后就碰到了瓶颈,因为随着业务的增长分拆过之后的dex文件方法数也超过65535个,更换拆包方案的话维护成本太高.同时由于没有做差异

Android热修复学习之旅——HotFix完全解析

在上一篇博客Android热修复学习之旅开篇--热修复概述中,简单介绍了各个热修复框架的原理,本篇博客我将详细分析QQ空间热修复方案. Android dex分包原理介绍 QQ空间热修复方案基于Android dex分包基础之上,简单概述android dex分包的原理就是:就是把多个dex文件塞入到app的classloader之中,但是android dex拆包方案中的类是没有重复的,如果classes.dex和classes1.dex中有重复的类,当classes.dex和classes1

Android热修复——Tinker微信解决方案

Android的热修复 前言: 随着时代的发展,由于公司的项目需要去求变化平凡计划总赶不上变化,H5的高灵活性,开发周期短,更新速度快H5以及一些混合开发越来越被看好,然而主要原因之一:这种混合开发的方式容错率大,更新和修复BUG快.不用发布版本就可以让用户不觉的情况下就更新对应的内容或者BUG,我们不能否认混合开发的快捷,正在此前提下热修复和热更新技术也得到了非常大的发展,不管热修复还是热更新,都是对app的内容或者逻辑变化做出像web页面更新一样的体验.而本文只对热修复进行探索,不对H5进行

Android 热修复使用Gradle Plugin1.5改造Nuwa插件

随着谷歌的Gradle插件版本号的不断升级,Gradle插件如今最新的已经到了2.1.0-beta1,相应的依赖为com.android.tools.build:gradle:2.0.0-beta6,而Nuwa当时出来的时候,Gradle插件还仅仅是1.2.3版本号,相应的依赖为com.android.tools.build:gradle:1.2.3,当时的Nuwa是依据有无preDex这个Task进行hook做不同的逻辑处理,而随着Gradle插件版本号的不断增加,谷歌增加了一个新的接口能够用