### 64K方法数限制原理与解决方案
64K方法数问题也有人称之为65K方法数问题,本质上都是指Android Dalvik可执行文件.dex中的Java方法数引用超过65536,64K的计算方法是65536除以1024,65K的计算方法是65536除以1000,Android 64K的一次幂。
64K方法数问题的直观表现是在构建APP的时候出现编译错误,导致构建失败,提示too many field references
#### 64K限制的原因
Android Apk 文件本质上是个压缩文件,它里面包含的class.dex文件是可执行的Dalvik字节码文件,这个.dex文件中存放的是所有编译后的Java代码。Dalvil可执行文件规范限制了(事实上是最初设计上的一个失误)单个.dex文件最多能引用的方法数是65536个,这其中包含了Android Framework、APP引用的第三方函数库以及APP自身的方法。
android 5.0 (API level 21)之前,系统使用的是Dalvik虚拟机来执行Android应用,默认情况下,Dalvik为每个APK只生成一个classes.dex文件,为了避免单个.dex文件方法数超过64K的问题,我们需要拆分这个单一的classes.dex文件,拆分后可能存在类似于classes.dex、classes2.dex等多个.dex文件。在应用启动后,会先加载classes.dex文件,我们称之为主(Primary)dex文件,应用启动后才会依次加载其他.dex文件,这些统称为从(Secondary)dex文件。为了规避这个64K限制,Google推出了一个名为MultiDex Support Library的函数库,当我们下载了Android Support Libraries之后,可以在<sdk>/extras/android/support/multidex/目录中找到这个函数库
### Android 5.0 之后的版本
从API21及之后的版本Android使用名为ART的虚拟机来代替Dalvik虚拟机,ART天然支持从APK文件中加载多个.dex文件,在应用安装期间,他会执行一个预编译操作,扫描APK中的classes(..N).dex文件并将它们编译成一个单一的.oat文件,在应用运行时去加载这个.oat文件,而不是一个个的加载.dex文件。
### 避免出现64K限制
当app开始触碰到64K方法数的天花板时,不建议立即视同MultiDex Support Library来将apk中的单一.dex拆分成多个,从而规避64K方法数限制引起的编译错误问题。最佳实践是永远保持应用的方法数低于64K,永远没有机会使用MultiDex Support Library,因为使用MultiDex是下下策,在大多数情况下会降低应用的性能,减少应用方法数的方法:
* 检查应用的直接和简洁第三方依赖
* 使用Proguard移除无用的代码:配置并在Release版本中使用ProGuard,它通过分析字节码压缩功能,能够检测并移除没有使用到的类、字段、方法和属性
如果使用以上方法没法将方法数限制在64K以下,那么就需要使用MultiDex,需要在应用module的build.gradle文件的defaultConfig中添加multiDexEnabled true,接着引入MultiDexApplication 初始化MultiDex。
#### MultiDex局限性
MultiDex Support Library是一个不得已而为之的方案,它本身不是完美的,将它集成到项目中,需要经过完整的测试才能上线,可能会出现应用性能下降等问题,具体局限性如下:
* 应用首次启动时Dalvik虚拟机会对所有的.dex文件执行dexopt操作,生成ODEX文件,这个过程很复杂且非常耗时,如果应用的从dex文件太大,可能会导致出现ANR。
* 在Android 4.0(API level 14)之前的系统上,由于Dalvik linearAlloc的bug,使用MultiDex的应用可能启动失败。
* 引入MultiDex机制时,必然会存在主dex文件和从dex文件,应用启动所需要的类都必须放到主dex文件中,否则会出现NoClassDefFoundError的错误。
64K方法数问题也有人称之为65K方法数问题,本质上都是指Android Dalvik可执行文件.dex中的Java方法数引用超过65536,64K的计算方法是65536除以1024,65K的计算方法是65536除以1000,Android 64K的一次幂。
64K方法数问题的直观表现是在构建APP的时候出现编译错误,导致构建失败,提示too many field references
#### 64K限制的原因
Android Apk 文件本质上是个压缩文件,它里面包含的class.dex文件是可执行的Dalvik字节码文件,这个.dex文件中存放的是所有编译后的Java代码。Dalvil可执行文件规范限制了(事实上是最初设计上的一个失误)单个.dex文件最多能引用的方法数是65536个,这其中包含了Android Framework、APP引用的第三方函数库以及APP自身的方法。
android 5.0 (API level 21)之前,系统使用的是Dalvik虚拟机来执行Android应用,默认情况下,Dalvik为每个APK只生成一个classes.dex文件,为了避免单个.dex文件方法数超过64K的问题,我们需要拆分这个单一的classes.dex文件,拆分后可能存在类似于classes.dex、classes2.dex等多个.dex文件。在应用启动后,会先加载classes.dex文件,我们称之为主(Primary)dex文件,应用启动后才会依次加载其他.dex文件,这些统称为从(Secondary)dex文件。为了规避这个64K限制,Google推出了一个名为MultiDex Support Library的函数库,当我们下载了Android Support Libraries之后,可以在<sdk>/extras/android/support/multidex/目录中找到这个函数库
### Android 5.0 之后的版本
从API21及之后的版本Android使用名为ART的虚拟机来代替Dalvik虚拟机,ART天然支持从APK文件中加载多个.dex文件,在应用安装期间,他会执行一个预编译操作,扫描APK中的classes(..N).dex文件并将它们编译成一个单一的.oat文件,在应用运行时去加载这个.oat文件,而不是一个个的加载.dex文件。
### 避免出现64K限制
当app开始触碰到64K方法数的天花板时,不建议立即视同MultiDex Support Library来将apk中的单一.dex拆分成多个,从而规避64K方法数限制引起的编译错误问题。最佳实践是永远保持应用的方法数低于64K,永远没有机会使用MultiDex Support Library,因为使用MultiDex是下下策,在大多数情况下会降低应用的性能,减少应用方法数的方法:
* 检查应用的直接和简洁第三方依赖
* 使用Proguard移除无用的代码:配置并在Release版本中使用ProGuard,它通过分析字节码压缩功能,能够检测并移除没有使用到的类、字段、方法和属性
如果使用以上方法没法将方法数限制在64K以下,那么就需要使用MultiDex,需要在应用module的build.gradle文件的defaultConfig中添加multiDexEnabled true,接着引入MultiDexApplication 初始化MultiDex。
#### MultiDex局限性
MultiDex Support Library是一个不得已而为之的方案,它本身不是完美的,将它集成到项目中,需要经过完整的测试才能上线,可能会出现应用性能下降等问题,具体局限性如下:
* 应用首次启动时Dalvik虚拟机会对所有的.dex文件执行dexopt操作,生成ODEX文件,这个过程很复杂且非常耗时,如果应用的从dex文件太大,可能会导致出现ANR。
* 在Android 4.0(API level 14)之前的系统上,由于Dalvik linearAlloc的bug,使用MultiDex的应用可能启动失败。
* 引入MultiDex机制时,必然会存在主dex文件和从dex文件,应用启动所需要的类都必须放到主dex文件中,否则会出现NoClassDefFoundError的错误。