文章

Android进阶指南

Android进阶指南

65535 问题(64K 问题)

出现这个问题的根本原因是在 DVM 源码中的 MemberIdsSection.java 类中,有如下一段代码:
5qdc3

如果 items 个数超过 DexFormat.MAX_MEMBER_IDX 则会报错,DexFormat.MAX_MEMBER_IDX 的值为 65535,items 代表 dex 文件中的方法个数、属性个数、以及类的个数。也就是说理论上不止方法数,我们在 java 文件中声明的变量,或者创建的类个数如果也超过 65535 个,同样会编译失败,Android 提供了 MultiDex 来解决这个问题。很多网上的文章说 65535 问题是因为解析 dex 文件到数据结构 DexFile 时,使用了 short 来存储方法的个数,其实这种说法是错误的!
解决:MultiDex

Multidex 分包技术

1、分包的原因?

64K 的问题,dex 的 items 超过了 DexFormat.MAX_MEMBER_IDX 即 65535 限制(items 代表有方法个数、属性个数、类的个数等)

2、解决

用 multidex

3、MultiDex 实现原理

  1. MultiDex 工作流程分为 2 个部分,一个部分是打包构建 apk 的时候,将 dex 文件拆分若干个小的 dex 文件
  2. 另外一个部分是在启动 apk 的时候,同时加载多个 dex 文件(具体是加载 Dex 文件优化后的 odex 文件,不过文件名还是.dex),这一部分工作从 Android5.0 开始系统已经帮我们做了,但是 Android5.0 之前还是需要通过 MultiDex 库来支持。

4、Multidex 的局限性

  1. Application Not Responding 如果第二个(或其他个)dex 文件很大的话,安装.dex 文件到 data 分区时可能会导致 ANR(应用程序无响应),此时应该使用 ProGuard 减小 DEX 文件的大小
  2. 由于 Dalvik linearAlloc 的 bug 的关系,使用了 multidex 的应用可能无法在 Android 4.0 (API level 14) 或之前版本的设备上运行

如何手动分包?

插件化和热修复

热修复

热修复原理

1、ARTMethod

AndFix

2、dex 替换

Nuwa,Tinker

3、InstantRun

代表就是美团的 Robust

Tinker 原理

  1. 使用 DexClassLoader 加载补丁包的 dex 文件
  2. 通过反射获取 DexClassLoader 类的 pathList(DexPathList),再次通过反射获得 dexElements 数组。
  3. 获取加载应用类的 PathClassLoader,同样通过反射获取它的 dexElements 数组。
  4. 合并两个 dexElements 数组,且将补丁包的 dex 文件放在前面。

根据类加载机制,一个类只会被加载一次,DexPathList.findClass 方法中是顺序遍历数组,所以将补丁的 dex 文件放在前面,这样 bug 修复类会被优先加载,而原来的 bug 类不会被加载,达到了替换 bug 类的功能(补丁包中的修复类名、包名要和 bug 类相同)

  1. 再次通过反射将合并后的 dexElements 数组赋值给 PathClassLoader.dexElements 属性。

插件化

1、占坑式原理

  1. 占坑 Activity
  2. hook Instrumention
  3. 替换占坑 Activity

插件化和热修复对比

插件化和热修复的原理,都是动态加载 dex/apk 中的类/资源,两者的目的不同。插件化目标在于加载 activity 等组件,达到动态下发组件的功能,热修复目标在修复已有的问题。目标不同,也就导致其实现方式上的差别。由于目标是动态加载组件,所以插件化重在解决组件的生命周期,以及资源的问题。而热修复重在解决替换已有的有问题的类/方法/资源等。

本文由作者按照 CC BY 4.0 进行授权