Android Studio Apply Changes
Aug 6, 2019
探究 Android Studio 3.5 新增的 Apply Changes
功能。
- Android Studio Project Marble: Apply Changes
- Android Studio 3.5提供的”Apply Changes“是什么原理?
- Source Code
- JVM(TM) Tool Interface
- JVMTI开发教程之一个简单的Agent
- JVMTI 和 Agent 实现
Instant Run
- 构建过程动手脚
- Apk 里藏私货
- 自定义 ClassLoader 热部署
- 兼容性一般
Apply Changes
- 不关心构建过程,只对 apk 做 diff
- 基于 JVMTI,需要 Android O+
基本流程
- 对设备上安装的 apk 与新 apk 做 diff
- 将 diff 推到设备上并应用改动
改动类型支持
- 仅 res/assets 改动:应用改动的资源,重启 Activity
- 仅 dex 改动:改动不能影响对象的内存布局,基于 JVMTI 进行类级别的 hot swap
- 资源改动 + dex 改动
- 其他改动:不支持
增量更新流程
- 解析新 apk 的 zip entries
- 拉取已安装的 apk 的 zip entries
- 对以上两个列表做 diff,得出变更文件的列表
- 根据文件列表 diff 验证是否支持 apply changes(是否改动 dex,资源之外的内容)
- 根据 diff 计算(粒度为 zip entry 级别)dirty map,生成 instructions & patch。注意这里不需要全量拉取已安装的 apk。
- deltaPreInstall:adb 调用
cmd package install-create
创建 session,install-write
写入 instructions & patch 数据。 - 对 dex (里的类)进行 diff,得到需要 swap 的类列表。这里注意两点:
(1)类的 diff 只用比较 checksum
(2)dex 里类的信息其实是从数据库取的(预先写进去的)而非拉取设备上的 dex, ( >﹏<。)~ 这个问题卡了我好久,其实流程图上有写。 - Swap!adb 调用
installer
执行 swap - Commit install
Swap & JVMTI Agent
installer
进程开启一个 socket server- 通过
cmd activity attach-agent <PROCESS> <FILE>
attach agent 到指定进程 - Attach 成功后,agent 通过 socket 从
installer
读取数据 - InstrumentApplication:
- SetEventCallbacks:
callbacks.ClassFileLoadHook = Agent_ClassFileLoadHook
- 加载 instrumentation jar 包
RetransformClasses
,触发前面设置的ClassFileLoadHook
:HookActivityThread.handleDispatchPackageBroadcast()
,更新资源。
- SetEventCallbacks:
- HotSwap:RedefineClasses
代码结构
1 | agent/ JVMTI agent 实现,编译成 so 文件,拷贝到 app 的 data 目录下,通过 JVMTI attach 到对应的进程上。 |
核心逻辑可以参考 deployer/src/main/java/com/android/tools/deployer/Deployer.java 的 swap
方法,十分清晰。
1 | // Get the list of files from the local apks |