简介: 关于 Android 热修复方案——DexPatch 的介绍与使用说明

方案介绍

为了解决 Native 模块上线后的问题,mPaaS 提供了热修复功能,实现不发布客户端 apk 场景下的热修复。目前 Android 端热修复主要包括 andfix 和 dexpatch,考虑到 andfix 的版本兼容性,目前主要推荐使用 DexPatch

DexPatch 修复原理比较简单,就是在启动后通过 RPC 拉取当前需要下发的 jar 包地址,然后通过独立进程去下载 jar 包文件,下载完成后保存。在二次启动的时候 hook 系统的 classLoader,修改 DexPathList,在其数组的最前面加入一个有修改过的 class 的 dex 文件,使其拦截住数组后面的 dex 文件中同名的 class 的加载。

如下图所示,classloader 就会优先加载 Patch.dex 中的 Ding.class,而忽略 Classes.dex 中的 Ding.class,达到了替换的效果。

基于这样的原理,DexPatch 具有以下特征:

  1. 支持范围上:是基于类级别的替换,所以只支持 Java 模块的 patch,不支持非 Java 模块的 patch,比如 so 模块;
  2. 兼容性上:由于是代理了系统的 ClassLoader,使用的黑科技较少,所以整体方案兼容性较好;
  3. 生效时效性上:只能在下载 patch 后重启后才能生效,不支持实时生效;
  4. 成功率上:由于下载是使用的独立进程,减少了启动阶段主进程闪退对 patch 下载的影响,提升了下载的成功比例。

操作说明

以下是关于在 mPaaS 下使用 DexPatch 模块的主要步骤以及问题排查思路,方便开发者日常开发。

1. 触发 patch 拉取

启动阶段调用 MPHotpatch.init(),主要触发 Patch 信息的 RPC 请求,如果命中发布 Patch 发布规则,RPC 会返回 Patch 的 jar 包下载地址,客户端去触发下载,下载后保存在客户端私有目录/data/user/0/包名/dexpatch/patch/下。

2. 代码操作演示

以组件化模式接入为例,介绍下 Patch 发布的主要流程。

(1)代码改动前

需要保存改动前的构建产物,方便后续做 Patch 生成,地址在:build/intermediates/bundle/xxxx-raw.jar

(2)代码改动后

重新编译,保存构建产物,产物地址:build/intermediates/bundle/xxxx-raw.jar

(3)生成白名单配置

主要用于热修复包时用于指定修复的类,配置文件为 .txt 格式,该配置文件应包含并按顺序包含以下信息:
需要 Patch 的类。以 L 开头,后跟以混淆后真实类名。如果多个类,每行只可写一个。示例:Lxxx.xxx.clazzX设置 Patch 类型为 dexpatch。示例:PatchType: dexpatch

设置是否是静态 Bundle。默认为 false,如果是静态链接的 Bundle,需要显式设置为 true。示例:HostDex: true(*目前 mPaaS 客户端的模块一般都在静态链接里,一般写 true)

(4)查看签名

生成 patch 需要用到项目的打包秘钥,需要提前准备好,可以在打包脚步下找到对应的配置

(5)生成 patch

① 通过 mPaaS 自带的 IDE 工具,点击热修复,进入修复页面。

② 按照页面提示,填入之前准备的修复前和修复后的 jar 包地址,还有白名单配置文件,勾选 dexPatch,进入到下一步

③ 下一步主要选择打包的配置文件,最近点击完成生成 patch 文件

(6)生成 patch 产物

生成 patch 产物如下:

查看产物,可以使用 dex2jar 工具反解 diff.dex 文件,用 jd-gui 文件查看反解产物是否符合预期

反解后可以看到修改的模块:

(7)上传发布

① 选择上一步的产物 jar 包进行上传

② 上传后可以通过白名单进行发布,验证 patch 的稳定性

(8)验证下载

白名单发布后,启动客户端,搜索关键字:DynamicRelease,可以看到在 tool 进程有触发下载的日志打出。
这里需要说明的是,这里触发 patch 的下载是在 tool 进程,不在主进程的主要原因是怕由于主进程由于启动导致重复闪退,导致 patch 不能下载成功,单独在 tool 进程实现下载,尽量提高 patch 的下载成功比例。

然后去下载目录查看,是否下载保存成功,下载目录在:/data/user/0/包名/dexpatch/patch/20201023110012@20201023110012.jar

(9)杀进程启动

确认下载保存成功后,杀掉 App,重启查看是否生效,重启可以搜索关键字:DexPatchManager,查看 patch 生效的日志,日志会打印当前是否存在 patch 以及 patch 是否加载的日志。

同时我们也可以就实际业务场景进行验证,查看是否生效。

常见问题

1. aar 模式集成后 patch 没生效

aar 模式集成的时候,需要继承框架的 QuinoxlessApplication,指定 Application 为框架的实现类才能实现 dexpatch 的加载。QuinoxlessApplication 内主要封装了 dexpatch 模块的初始化和加载。

2. 使用加固后不生效

需要使用加固前的 apk 生成 patch,不能用加固后的包生成 patch。然后还需要验证在不同加固厂商下的兼容表现。

3. 使用热修复后,和 RPC 有关的调用发生 apache http 相关的 crash。

请使用 Android 官网上的方式引入 apache http client,禁止使用导入 jar 包或者 gradle implementation/compile 的方式导入 http client。否则会引起 classloader 加载类混乱。

建议方式:

<uses-library android:name="org.apache.http.legacy" android:required="false"/>

E · N · D

原文链接

本文为阿里云原创内容,未经允许不得转载

技术干货 | 深度解构 Android 应用面临紧急发版时的救星方案:mPaaS 热修复——DexPatch的更多相关文章

  1. 华为全栈AI技术干货深度解析,解锁企业AI开发“秘籍”

    摘要:针对企业AI开发应用中面临的痛点和难点,为大家带来从实践出发帮助企业构建成熟高效的AI开发流程解决方案. 在数字化转型浪潮席卷全球的今天,AI技术已经成为行业公认的升级重点,正在越来越多的领域为 ...

  2. Android热修复技术原理详解(最新最全版本)

    本文框架 什么是热修复? 热修复框架分类 技术原理及特点 Tinker框架解析 各框架对比图 总结   通过阅读本文,你会对热修复技术有更深的认知,本文会列出各类框架的优缺点以及技术原理,文章末尾简单 ...

  3. JavaScript学习笔记(八)——变量的作用域与解构赋值

    在学习廖雪峰前辈的JavaScript教程中,遇到了一些需要注意的点,因此作为学习笔记列出来,提醒自己注意! 如果大家有需要,欢迎访问前辈的博客https://www.liaoxuefeng.com/ ...

  4. ES6知识整理(2)--变量的解构赋值

    最近准备在业余空闲时间里一边学习ES6,一边整理相关知识.只有整理过的学习才是有效的学习.也就是学习之后要使用和整理成文,才是真正的学到了... 上一篇是一个试水,现在接上. 变量提升 看了下朋友回复 ...

  5. ES2015中的解构赋值

    ES2015中允许按照一定的模式,从数组和对象中提取值,对变量进行赋值,被称为”解构(Destructering)“. 以前,为变量赋值,只能指定值. /** * 以前,为变量赋值,只能直接指定值 * ...

  6. Python函数参数与参数解构

    1 Python中的函数 函数,从数学的角度来讲是,输入一个参数,经过一个表达式的处理后得到一个结果的输出,即就是x-->y的一个映射.同样,在Python或者任何编程语言中,函数其实就是实现一 ...

  7. ES6--JavaScript扩展知识点(let、const、解构)

    一,ES2015(ES6)新增了两个声明变量的关键字:let.const let:只在代码块内{}有效,不可重复声明,不会提前初始化 1.只在代码块内有效 { let a = 1; var b = 2 ...

  8. JavaScript 中对象解构时指定默认值

    待解构字段为原始值 正常情况下, const obj = { a: 1, b: 2, }; const { a, b } = obj; console.log(a, b); // 1 2 当被解构字段 ...

  9. Android 插件化和热修复知识梳理

    概述 在Android开发中,插件化和热修复的话题越来越多的被大家提及,同时随着技术的迭代,各种框架的发展更新,插件化和热修复的框架似乎已经日趋成熟,许多开发者也把这两项技术运用到实际开发协作和正式的 ...

  10. Android 热修复Nuwa的原理及Gradle插件源码解析

    现在,热修复的具体实现方案开源的也有很多,原理也大同小异,本篇文章以Nuwa为例,深入剖析.  Nuwa的github地址 https://github.com/jasonross/Nuwa 以及用于 ...

随机推荐

  1. 封装TornadoFx常用控件库

    github:https://github.com/Stars-One/common-controls 为TornadoFx的封装的常用控件与工具,基于Jfoenix,借鉴Kfoenix 前言 这个开 ...

  2. 【leetcode 952. 按公因数计算最大组件大小】【欧拉筛+并查集】

    import java.util.ArrayList; import java.util.Arrays; import java.util.List; class Solution { List< ...

  3. 01.Android崩溃Crash封装库

    目录介绍 01.该库具有的功能 02.该库优势分析 03.该库如何使用 04.降低非必要crash 05.异常恢复原理 06.后续的需求说明 07.异常栈轨迹原理 08.部分问题反馈 09.其他内容说 ...

  4. 介绍几款WPF应用的UI库

    在WPF中对于前端页面的书写,我们有现成的UI类库,不需要我们自己再去写 我这里介绍几款 1.MahApps 官网 https://mahapps.com/ 使用,在App.xaml中添加 <A ...

  5. AntSK 0.2.3 版本更新:轻松集成 AI 本地离线模型

    大家好,今天和大家分享 AntSK 知识库/智能体项目的最新进展. AntSK 是一个基于 .Net 8.Blazor 及 SemanticKernel 开发的 AI 项目,旨在为开发者提供一个强大的 ...

  6. %USERPROFILE% 查看系统变量

    %USERPROFILE% =C:\Users\用户名 win+r,输入cmd 回车 在cmd窗口下输入 set 回车,可以查看系统变量(想要了解更多 set 命令请看 这里)

  7. ZYNQ学习系列之GPIO

    ZYNQ学习系列之GPIO 一.GPIO含义 general purpose IO ,通用目标的IO.所谓通用,就是采用常用的电压标准和电流标准的控制器IO接口,可以初步理解为开发板上的IO口.这种接 ...

  8. KingbaseES 分区表修改字段类型

    KingbaseES普通表修改表结构请参考:KingbaseES变更表结构表重写问题 数据类型转换重写与不重写: varchar(x) 转换到 varchar(y) 当 y>=x,不需要重写. ...

  9. 循环队列(LoopQueue)

    循环队列相比普通的队列,元素出队时无需移动大量元素. 代码 ArrayQueue.h 点它 代码清单 #ifndef C___LOOPQUEUE_H #define C___LOOPQUEUE_H # ...

  10. 论文阅读:A new approach solve the multi-product multi-period inventory lot sizing with supplier selection problem

    论文:A new approach solve the multi-product multi-period inventory lot sizing with supplier selection ...