Android热更新实现原理
最近Android社区的氛围很不错嘛,连续放出一系列的android动态加载插件和热更新库,这篇文章就来介绍一下Android中实现热更新的原理。
ClassLoader
我们知道Java在运行时加载对应的类是通过ClassLoader来实现的,ClassLoader本身是一个抽象来,Android中使用PathClassLoader类作为Android的默认的类加载器,
PathClassLoader其实实现的就是简单的从文件系统中加载类文件。PathClassLoade本身继承自BaseDexClassLoader,BaseDexClassLoader重写了findClass方法,
该方法是ClassLoader的核心
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
List<Throwable> suppressedExceptions = new ArrayList<Throwable>();
Class c = pathList.findClass(name, suppressedExceptions);
if (c == null) {
ClassNotFoundException cnfe = new ClassNotFoundException("Didn't find class \"" + name + "\" on path: " + pathList);
for (Throwable t : suppressedExceptions) {
cnfe.addSuppressed(t);
}
throw cnfe;
}
return c;
}
- 1
- 2
看源码可知,BaseDexClassLoader将findClass方法委托给了pathList对象的findClass方法,pathList对象是在BaseDexClassLoader的构造函数中new出来的,
它的类型是DexPathList。看下DexPathList.findClass源码是如何做的:
public Class findClass(String name, List<Throwable> suppressed) {
for (Element element : dexElements) {
DexFile dex = element.dexFile;
if (dex != null) {
Class clazz = dex.loadClassBinaryName(name, definingContext, suppressed);
if (clazz != null) {
return clazz;
}
}
}
if (dexElementsSuppressedExceptions != null) {
suppressed.addAll(Arrays.asList(dexElementsSuppressedExceptions));
}
return null;
}
- 1
- 213
直接就是遍历dexElements列表,然后通过调用element.dexFile对象上的loadClassBinaryName方法来加载类,如果返回值不是null,就表示加载类成功,会将这个Class对象返回。
而dexElements对象是在DexPathList类的构造函数中完成初始化的。
this.dexElements = makeDexElements(splitDexPath(dexPath), optimizedDirectory,
suppressedExceptions);
makeDexElements所做的事情就是遍历我们传递来的dexPath,然后一次加载每个dex文件。
实现
上面分析了Android中的类的加载的流程,可以看出来DexPathList对象中的dexElements列表是类加载的一个核心,一个类如果能被成功加载,那么它的dex一定
会出现在dexElements所对应的dex文件中,并且dexElements中出现的顺序也很重要,在dexElements前面出现的dex会被优先加载,一旦Class被加载成功,
就会立即返回,也就是说,我们的如果想做hotpatch,一定要保证我们的hotpacth dex文件出现在dexElements列表的前面。
要实现热更新,就需要我们在运行时去更改PathClassLoader.pathList.dexElements,由于这些属性都是private的,因此需要通过反射来修改。另外,构造我们自己的dex文件
所对应的dexElements数组的时候,我们也可以采取一个比较取巧的方式,就是通过构造一个DexClassLoader对象来加载我们的dex文件,并且调用一次dexClassLoader.loadClass(dummyClassName);
方法,这样,dexClassLoader.pathList.dexElements中,就会包含我们的dex,通过把dexClassLoader.pathList.dexElements插入到系统默认的classLoader.pathList.dexElements列表前面,就可以让系统优先加载我们的dex中的类,从而可以实现热更新了。下面展示一部分代码
private static synchronized Boolean injectAboveEqualApiLevel14(
String dexPath, String defaultDexOptPath, String nativeLibPath, String dummyClassName) {
Log.i(TAG, "--> injectAboveEqualApiLevel14");
PathClassLoader pathClassLoader = (PathClassLoader) DexInjector.class.getClassLoader();
DexClassLoader dexClassLoader = new DexClassLoader(dexPath, defaultDexOptPath, nativeLibPath, pathClassLoader);
try {
dexClassLoader.loadClass(dummyClassName);
Object dexElements = combineArray(
getDexElements(getPathList(pathClassLoader)),
getDexElements(getPathList(dexClassLoader)));
Object pathList = getPathList(pathClassLoader);
setField(pathList, pathList.getClass(), "dexElements", dexElements);
} catch (Throwable e) {
e.printStackTrace();
return false;
}
Log.i(TAG, "<-- injectAboveEqualApiLevel14 End.");
return true;
}
完整的demo请参考我的GitHub
上面只是说了一下hotpatch的原理,具体实现的时候,如果你的app应用了multidex,还会遇到其他的坑,请参考:
Android热更新实现原理的更多相关文章
- 【原】Android热更新开源项目Tinker源码解析系列之三:so热更新
本系列将从以下三个方面对Tinker进行源码解析: Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Android热更新开源项目Tinker源码解析系列之二:资源文件热更新 A ...
- 【原】Android热更新开源项目Tinker源码解析系列之一:Dex热更新
[原]Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Tinker是微信的第一个开源项目,主要用于安卓应用bug的热修复和功能的迭代. Tinker github地址:http ...
- 【原】Android热更新开源项目Tinker源码解析系列之二:资源文件热更新
上一篇文章介绍了Dex文件的热更新流程,本文将会分析Tinker中对资源文件的热更新流程. 同Dex,资源文件的热更新同样包括三个部分:资源补丁生成,资源补丁合成及资源补丁加载. 本系列将从以下三个方 ...
- Android热更新开源项目Tinker集成实践总结
前言 最近项目集成了Tinker,开始认为集成会比较简单,但是在实际操作的过程中还是遇到了一些问题,本文就会介绍在集成过程大家基本会遇到的主要问题. 考虑一:后台的选取 目前后台功能可以通过三种方式实 ...
- Android热修复技术原理详解(最新最全版本)
本文框架 什么是热修复? 热修复框架分类 技术原理及特点 Tinker框架解析 各框架对比图 总结 通过阅读本文,你会对热修复技术有更深的认知,本文会列出各类框架的优缺点以及技术原理,文章末尾简单 ...
- Android 热更新是如何实现的?
Android开发中,我们常常遇到热更新这个概念,而这个热更新具体是怎么实现的呢?今天在网上看到一个大神分享的热更新相关实现原理和实现代码,感觉灰常不错,分享给广大码农盆友look look . Cl ...
- Android热修复技术原理详解
阿里Dexposed -- native解决方案 原理: 直接在native层进行方法的结构体信息对换,从而实现完美的方法新旧替换,从而实现热修复功能 他的思想完全来源于Xposed框架,完美诠释 ...
- 深入探索Android热修复技术原理读书笔记 —— 热修复技术介绍
1.1 什么是热修复 对于广大的移动开发者而言,发版更新是最为寻常不过的事了.然而,如果你 发现刚发出去的包有紧急的BUG需要修复,那你就必须需要经过下面这样的流程: 这就是传统的更新流程,步骤十分繁 ...
- 深入探索Android热修复技术原理读书笔记 —— 资源热修复技术
该系列文章: 深入探索Android热修复技术原理读书笔记 -- 热修复技术介绍 深入探索Android热修复技术原理读书笔记 -- 代码热修复技术 1 普遍的实现方式 Android资源的热修复,就 ...
随机推荐
- android计算屏幕dp
首先我们来了解一些基本元素: px:像素,屏幕上的点. dpi:一英寸长的直线上的像素点的数量,即像素密度.标准值是160dp. /*** 正是因为dpi值其代表的特性,所以android项目的资源文 ...
- DeltaFish 校园物资共享平台 第八次小组会议
DeltaFish 校园物资共享平台 第八次小组会议 记录人:娄雨禛 2018.7.31 会议总结 1. 对前端界面进行改进,具体改进内容如下: 2. 后端从登录和注册的具体实现做起,熟悉流程之后完成 ...
- oracle for linux服务器磁盘空间不足,通过过期的文件释放磁盘空间
--2013-09-16截取的数据-- 使用df-h命令查看系统磁盘空间 [root@erpdbs PROD]# df -h Filesystem Size Used Avail Use% Mount ...
- SpringBoot 搭建
1.使用Eclipse 建立Maven项目(webapp OR quickstart) 2.配置Maven,如下: <parent> <groupId>org.springfr ...
- Ajax无刷新显示
前台页面 <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1. ...
- js 根据数组分组动态生成table(相同项合并)
<!doctype html public "-//w3c//dtd html 4.01 transitional//en" "http://www.w3.org/ ...
- 爬虫系列(三) urllib的基本使用
一.urllib 简介 urllib 是 Python3 中自带的 HTTP 请求库,无需复杂的安装过程即可正常使用,十分适合爬虫入门 urllib 中包含四个模块,分别是 request:请求处理模 ...
- git 的简单使用(4)
多人协作的工作模式通常是这样: 首先,可以试图用git push origin <branch-name>推送自己的修改: 如果推送失败,则因为远程分支比你的本地更新,需要先用git pu ...
- Dijkstra算法求最短路径
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <limits.h&g ...
- Huawei-R&S-网络工程师实验笔记20190527-华为设备密码重置、设置web管理
>Huawei-R&S-网络工程师实验笔记20190527-华为设备密码重置.设置web管理 >>实验开始(使用SecureCRT 等工具软件): 一.华为设备密码重置,通过 ...