[TOC]
# 插件化实现
## 类加载
### java 中的 ClassLoader
BootstrapClassLoader
负责加载 JVM 运行时的核心类,比如 JAVA\_HOME/lib/rt.jar 等等。
ExtensionClassLoader
负责加载 JVM 的扩展类,比如 JAVA\_HOME/lib/ext 下面的 jar 包。
AppClassLoader
负责加载 classpath 里的 jar 包和目录。
### android 中的 ClassLoader
BootClassLoader <- PathClassLoader
在这里,我们统称 dex 文件,包含 dex 的 apk 文件以及 jar 文件为 dex 文件 PathClassLoader 用来加载系统类和应用程序类,可以加载已经安装的 apk 目录下的 dex 文件。
DexClassLoader 用来加载 dex 文件,可以从存储空间加载 dex 文件。
我们在插件化中一般使用的是 DexClassLoader。
~~~
// 从 assets 中拿出插件 apk 放到内部存储空间
private fun extractPlugin() {
var inputStream = assets.open("plugin.apk")
File(filesDir.absolutePath, "plugin.apk").writeBytes(inputStream.readBytes())
}
private fun init() {
extractPlugin()
pluginPath = File(filesDir.absolutePath, "plugin.apk").absolutePath
nativeLibDir = File(filesDir, "pluginlib").absolutePath
dexOutPath = File(filesDir, "dexout").absolutePath
// 生成 DexClassLoader 用来加载插件类
//pluginPath 是需要加载的 dex / apk / jar 文件路径。
//dexOutPath 是 dex 优化后存放的位置,在 ART 上,会执行 oat 对 dex 进行优化,生成机器码,这里就是存放优化后的 odex 文件的位置。
//librarySearchPath 是 native 依赖的位置。
parent 就是父类加载器,默认会先从 parent 加载对应的
pluginClassLoader = DexClassLoader(pluginPath, dexOutPath, nativeLibDir, this::class.java.classLoader)
}
~~~
### 双亲委派
每一个 ClassLoader 中都有一个 parent 对象,代表的是父类加载器,在加载一个类的时候,会先使用父类加载器去加载,如果在父类加载器中没有找到,自己再进行加载,如果 parent 为空,那么就用系统类加载器来加载。
## activity的hook
方法1、我们手动去调用插件 Activity 的生命周期。
方法2、欺骗系统,让系统以为 Activity 是注册在 Manifest 中的。
| 现方法 | 优点 | 缺点 |
| --- | --- | --- |
| 手动调用 | 1\. 比较稳定,不需要 hook 系统实现 2. 实现相对简单,不需要对系统内部实现做过多了解 | 通过反射效率太低,通过接口需要实现的方法数量很多 |
| hook 系统 | 1\. 不需要实现大量接口方法 2. 由于最终还是交给系统去处理,各种处理相对比较完整 | 1\. 需要适配不同的系统及设备 2. 对开发者要求比较高,需要对系统实现有深入的了解 |
#### hook系统(Instrumentation)
![](https://img.kancloud.cn/a9/62/a96261c2e568d197863ae56fbfab82c3_640x240.png)
有两个关键点,execStartActivity 和 newActivity。
execStartActivity 是在启动 Activity 的时候必经的一个过程,这时还没有到达 AMS,所以,在这里把 Activity 替换成宿主中已经注册的 StubActivity,这样 AMS 在检测 Activity 的时候就认为已经注册过了。newActivity 是创建 Activity 实例,这里要返回真正需要运行的插件 Activity,这样后面系统就会基于这个 Activity 实例来进行对应的生命周期的调用。
资源
## shadow实现
### Manager VS Loader VS Container
Manager的功能就是管理插件,包括插件的下载逻辑、入口逻辑,预加载逻辑等.反正就是一切还没有进入到Loader之前的所有事情。
Loader就是负责加载插件Activity,然后实现插件Activity的生命周期等功能的那部分核心逻辑了。
Container就是那些注册在宿主AndroidManifest中的代理壳子。由于Activity的创建是系统根据Activity的名字直接通过宿主的PathClassLoader构造的,所以这些Activity必须打包在宿主中才能处于PathClassLoader,才能被系统找到。所以Container是不能放到Loader中,通过动态加载的一般方法加载的。因为前面提到的一般方法都是要new一个新的ClassLoader加载动态实现的。
### ClassLoader
我们可以通过修改ClassLoader的parent,为ClassLoader新增一个parent。将原本的
~~~
BootClassLoader <- PathClassLoader
~~~
结构变为
~~~
BootClassLoader <- DexClassLoader <- PathClassLoader
~~~
,插入的DexClassLoader加载了ContainerActivity就可以使得系统在向PathClassLoader查找ContainerActivity时能够正确找到实现。
### Activity
核心:加入的ShadowActivity就是这个中间层。通过这个中间层让Android系统看不到插件,也让插件看不到Android系统。
技术:字节码插桩
# 参考资料
[Shadow源码解析](https://github.com/ChenSiLiang/android-toy/blob/master/Shadow%E6%BA%90%E7%A0%81%E8%A7%A3%E6%9E%90%E7%AC%94%E8%AE%B0/Shadow%E6%BA%90%E7%A0%81%E8%A7%A3%E6%9E%90.md)
[Android 插件化的今生前世大揭秘](https://mp.weixin.qq.com/s/EuCqudpPnBRidtmZBocNYg)
- Android
- 四大组件
- Activity
- Fragment
- Service
- 序列化
- Handler
- Hander介绍
- MessageQueue详细
- 启动流程
- 系统启动流程
- 应用启动流程
- Activity启动流程
- View
- view绘制
- view事件传递
- choreographer
- LayoutInflater
- UI渲染概念
- Binder
- Binder原理
- Binder最大数据
- Binder小结
- Android组件
- ListView原理
- RecyclerView原理
- SharePreferences
- AsyncTask
- Sqlite
- SQLCipher加密
- 迁移与修复
- Sqlite内核
- Sqlite优化v2
- sqlite索引
- sqlite之wal
- sqlite之锁机制
- 网络
- 基础
- TCP
- HTTP
- HTTP1.1
- HTTP2.0
- HTTPS
- HTTP3.0
- HTTP进化图
- HTTP小结
- 实践
- 网络优化
- Json
- ProtoBuffer
- 断点续传
- 性能
- 卡顿
- 卡顿监控
- ANR
- ANR监控
- 内存
- 内存问题与优化
- 图片内存优化
- 线下内存监控
- 线上内存监控
- 启动优化
- 死锁监控
- 崩溃监控
- 包体积优化
- UI渲染优化
- UI常规优化
- I/O监控
- 电量监控
- 第三方框架
- 网络框架
- Volley
- Okhttp
- 网络框架n问
- OkHttp原理N问
- 设计模式
- EventBus
- Rxjava
- 图片
- ImageWoker
- Gilde的优化
- APT
- 依赖注入
- APT
- ARouter
- ButterKnife
- MMKV
- Jetpack
- 协程
- MVI
- Startup
- DataBinder
- 黑科技
- hook
- 运行期Java-hook技术
- 编译期hook
- ASM
- Transform增量编译
- 运行期Native-hook技术
- 热修复
- 插件化
- AAB
- Shadow
- 虚拟机
- 其他
- UI自动化
- JavaParser
- Android Line
- 编译
- 疑难杂症
- Android11滑动异常
- 方案
- 工业化
- 模块化
- 隐私合规
- 动态化
- 项目管理
- 业务启动优化
- 业务架构设计
- 性能优化case
- 性能优化-排查思路
- 性能优化-现有方案
- 登录
- 搜索
- C++
- NDK入门
- 跨平台
- H5
- Flutter
- Flutter 性能优化
- 数据跨平台