• 欢迎访问web前端中文站,JavaScript,CSS3,HTML5,web前端demo
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏web前端中文站吧

详解 Android 热更新升级如何突破底层结构差异?

JAVA web前端中文站 2年前 (2017-05-21) 908次浏览 未收录 0个评论

关于前面两篇关于 Android 热更新的文章《Android 热修复升级原理和实践》《Android 热修复升级、兼容性问题的根源》

更多精彩内容请看 web 前端中文站
http://www.lisa33xiaoq.net 可按 Ctrl + D 进行收藏

知道了 native 替换方式兼容性问题的原因,我们是否有办法寻求一种新的方式,不依赖于 ROM 底层方法结构的实现而达到替换效果呢?

我们发现,这样 native 层面替换思路,其实就是替换 ArtMethod 的所有成员。那么,我们并不需要构造出 ArtMethod 具体的各个成员字段,只要把 ArtMethod 的作为整体进行替换,这样不就可以了吗?

也就是把原先这样的逐一替换。

详解 Android 热更新升级如何突破底层结构差异?

变成了这样的整体替换。

详解 Android 热更新升级如何突破底层结构差异?

因此 Andfix 这一系列繁琐的替换:

详解 Android 热更新升级如何突破底层结构差异?

其实可以浓缩为:

详解 Android 热更新升级如何突破底层结构差异?

就是这样,一句话就能取代上面一堆代码,这正是我们深入理解替换机制的本质之后研发出的新替换方案。

刚才提到过,不同的手机厂商都可以对底层的 ArtMethod 进行任意修改,但即使他们把 ArtMethod 改得六亲不认,只要我像这样把整个 ArtMethod 结构体完整替换了,就能够把所有旧方法成员自动对应地换成新方法的成员。

但这其中最关键的地方,在于 sizeof(ArtMethod)。如果 size 计算有偏差,导致部分成员没有被替换,或者替换区域超出了边界,都会导致严重的问题。

对于 ROM 开发者而言,是在 art 源代码里面,所以一个简单的 sizeof(ArtMethod)就行了,因为这是在编译期就可以决定的。

但我们是上层开发者,app 会被下发给各式各样的 Android 设备,所以我们是需要在运行时动态地得到 app 所运行设备上面的底层 ArtMethod 大小的,这就没那么简单了。

想要忽略 ArtMethod 的具体结构成员直接取得其 size 的精确值,我们还是需要从虚拟机的源码入手,从底层的数据结构及排列特点探寻答案。

在 art 里面,初始化一个类的时候会给这个类的所有方法分配空间,我们可以看到这个分配空间的地方:

详解 Android 热更新升级如何突破底层结构差异?

类的方法有 direct 方法和 virtual 方法。direct 方法包含 static 方法和所有不可继承的对象方法。而 virtual 方法就是所有可以继承的对象方法了。

AllocArtMethodArray 函数分配了他们的方法所在区域。

详解 Android 热更新升级如何突破底层结构差异?

可以看到,ptr 是这个方法数组的指针,而方法是一个接一个紧密地 new 出来排列在这个方法数组中的。这时只是分配出空间,还没填入真正的 ArtMethod 的各个成员值,不过这并不影响我们观察 ArtMethod 的空间结构。

详解 Android 热更新升级如何突破底层结构差异?

正是这里给了我们启示,ArtMethod 们是紧密排列的,所以一个 ArtMethod 的大小,不就是相邻两个方法所对应的 ArtMethod 的起始地址的差值吗?

正是如此。我们就从这个排列特点入手,自己构造一个类,以一种巧妙的方式获取到这个差值。

详解 Android 热更新升级如何突破底层结构差异?

由于 f1 和 f2 都是 static 方法,所以都属于 direct ArtMethod Array。由于 NativeStructsModel 类中只存在这两个方法,因此它们肯定是相邻的。

那么我们就可以在 JNI 层取得它们地址的差值:

详解 Android 热更新升级如何突破底层结构差异?

然后,就以这个 methSize 作为 sizeof(ArtMethod),代入之前的代码。

详解 Android 热更新升级如何突破底层结构差异?

问题就迎刃而解了。

值得一提的是,由于忽略了底层 ArtMethod 结构的差异,对于所有的 Android 版本都不再需要区分,而统一以 memcpy 实现即可,代码量大大减少。即使以后的 Android 版本不断修改 ArtMethod 的成员,只要保证 ArtMethod 数组仍是以线性结构排列,就能直接适用于将来的 Android 8.0、9.0 等新版本,无需再针对新的系统版本进行适配了。事实也证明确实如此,当我们拿到 Google 刚发不久的 Android O(8.0)开发者预览版的系统时,hotfix demo 直接就能顺利地加载补丁跑起来了,我们并没有做任何适配工作,鲁棒性极好。

【注:本文源自网络文章资源,由站长整理发布】


web 前端中文站 , 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:详解 Android 热更新升级如何突破底层结构差异?
喜欢 (0)
发表我的评论
取消评论
表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址