热修复Tinker 原理解析之so更新

前言:之前已经在文章中对Tinker的Dex热更新、资源热更新的源码做了分析,今天接着开始对Tinker的so热更新做源码的分析,废话不多说直接出发。

Android tinker接入使用

tinker之dex更新详解

tinker之资源更新详解

开始先回顾一下Android里面关于so的加载的两种方式:

  • System.loadLibrary: 这种方式传入的是so的名字,会直接从系统的目录去加载so文件,系统的路径包括/data/data/${package_name}/lib、/system/lib、/vender/lib等这类路径。
  • System.load:这种方式传入的是so的绝对路径,直接从这个路径加载so文件。

相对于Dex和资源的更新,so文件的更新简单很多,Tinker的so文件热更新的原理就是通过方式二,直接加载新的so实现的。

so文件的热更新流程同dex、资源文件一样,包含补丁生成,补丁合成,补丁加载三个部分。

生成补丁时比较新旧so文件使用BSdiff算法生成补丁包,然后在下发补丁成功后根据BSpatch算法将补丁包和旧的library合成新的library,

并将更新后的Library库文件保存在tinker下面的目录下,这个目录就是/data/data/${package_name}/tinker/lib。然后在加载的时候直接通过System.load加载该目录下面的so文件。

友情提示:Tinker中so的热更新对用户并不是无感的,需要用户自发的去加载自己需要的库文件。

下面是tinker的wiki里关于这方面的描述:

Tinker并没有直接将补丁的lib路径添加到DexPathList中,理论上这样可以做到程序完全没有感知的对Library文件作补丁。这里主要是因为在多abi的情况下,某些机器获取的并不准确。

所以想要加载最新的库,需要自己使用TinkerInstaller.load*Library去加载库文件,它会自动尝试先去Tinker中的库文件加载,加载不成功会调用System.loadLibrary调用系统的库文件。

//load lib/armeabi library
TinkerInstaller.loadArmLibrary(getApplicationContext(), "stlport_shared");
//load lib/armeabi-v7a library
TinkerInstaller.loadArmV7Library(getApplicationContext(), "stlport_shared");

另外,对于第三方库文件的加载,Tinker无法干预其加载时机,但是只要在我们的代码提前加载第三方的库文件即可。若想对第三方代码的库文件更新,可先使用TinkerInstaller.load*Library对第三方库做提前的加载!

当前使用方式似乎并不能做到开发者透明,这是因为Tinker想尽量少的去hook系统框架减少兼容性的问题。

到此为止,tinker的源码解析系列结束。本系列从dex,资源文件和so的补丁生成,补丁合成和补丁加载角度出发,做了一个简要的流程分析。如果想要更加深入详细的讲解请查看更多的文档。

see you

你可能感兴趣的:(学无止境)