近日,Android Developers在Google+上宣布了新的Multidex支持库,为方法总数超过65K的Android应用提供了官方支持。如果你是一名幸运的Android应用开发者,正在开发一个前景广阔的应用,不断地加入新功能、添加新的类库,那么终有一天,你会不幸遇到这个错误:

近日,Android Developers在Google+上宣布了新的Multidex支持库,为方法总数超过65K的Android应用提供了官方支持。

如果你是一名幸运的Android应用开发者,正在开发一个前景广阔的应用,不断地加入新功能、添加新的类库,那么终有一天,你会不幸遇到这个错误:

Conversion to Dalvik format failed: Unable to execute dex: method ID not in [0, 0xffff]: 65536

这个错误是Android应用的方法总数限制造成的。Android平台的Java虚拟机Dalvik在执行DEX格式的Java应用程序时,使用原生类型short来索引DEX文件中的方法。这意味着单个DEX文件可被引用的方法总数被限制为65536。通常APK包含一个classes.dex文件,因此Android应用的方法总数不能超过这个数量,这包括Android框架、类库和你自己开发的代码。

这个问题可以通过将一个DEX文件分拆成多个DEX文件解决。Facebook介绍了为Android应用开发的Dalvik补丁;Android
Developers博客介绍了通过自定义类加载过程的方法来解决此问题。但这些方法有些复杂而且并不优雅。

随着新的MultiDex支持库发布,Google正式为解决此问题提供官方支持。构建超过65K方法数的应用介绍了如何使用Gradle构建多DEX应用。

首先使用Android SDK Manager升级到最新的Android SDK Build Tools和Android Support Library R21。然后进行以下两步操作:

1.修改Gradle配置文件,启用MultiDex并包含MultiDex支持:

``` android { compileSdkVersion 21 buildToolsVersion "21.1.0"

defaultConfig {

    ...

    minSdkVersion 14

    targetSdkVersion 21

    ...

// Enabling multidex support.

    multiDexEnabled true

}

...

}

dependencies { compile ’com.android.support:multidex:1.0.0’ } ```

2.让应用支持多DEX文件。在MultiDexApplication JavaDoc中描述了三种可选方法:

在AndroidManifest.xml的application中声明android.support.multidex.MultiDexApplication;

如果你已经有自己的Application类,让其继承MultiDexApplication;

如果你的Application类已经继承自其它类,你不想/能修改它,那么可以重写attachBaseContext()方法:

@Override

protected void attachBaseContext(Context base) {

super.attachBaseContext(base); MultiDex.install(this);

}

经过以上步骤,你的应用已经可以实现多个DEX文件了。当应用构建时,构建工具会分析哪些类必须放在第一个DEX文件,哪些类可以放在附加的DEX文件中。当它创建了第一个DEX文件(classes.dex)后,如果有必要会继续创建附加的DEX文件,如classes2.dex, classes3.dex。Multidex的支持类库将被包含在应用的第一个DEX文件中,帮助实现对其它DEX文件的访问。

文中还介绍了在开发多DEX应用时,通过设置productFlavors提高开发效率以及多DEX应用的测试方法。

Android 5.0和更高版本使用名为ART的运行时,它原生支持从APK文件加载多个DEX文件。在应用安装时,它会执行预编译,扫描classes(..N).dex文件然后将其编译成单个.oat文件用于执行。了解更多关于ART的信息。

虽然Google解决了应用总方法数限制的问题,但并不意味着开发者可以任意扩大项目规模。Multidex仍有一些限制:

  1. DEX文件安装到设备的过程非常复杂,如果第二个DEX文件太大,可能导致应用无响应。此时应该使用ProGuard减小DEX文件的大小。
  2. 由于Dalvik linearAlloc的Bug,应用可能无法在Android 4.0之前的版本启动,如果你的应用要支持这些版本就要多执行测试。
  3. 同样因为Dalvik linearAlloc的限制,如果请求大量内存可能导致崩溃。Dalvik linearAlloc是一个固定大小的缓冲区。在应用的安装过程中,系统会运行一个名为dexopt的程序为该应用在当前机型中运行做准备。dexopt使用LinearAlloc来存储应用的方法信息。Android 2.2和2.3的缓冲区只有5MB,Android 4.x提高到了8MB或16MB。当方法数量过多导致超出缓冲区大小时,会造成dexopt崩溃。
  4. Multidex构建工具还不支持指定哪些类必须包含在首个DEX文件中,因此可能会导致某些类库(例如某个类库需要从原生代码访问Java代码)无法使用。

避免应用过大、方法过多仍然是Android开发者要注意的问题。Mihai Parparita的开源项目dex-method-counts可以用于统计APK中每个包的方法数量。

通常开发者自己的代码很难达到这样的方法数量限制,但随着第三方类库的加入,方法数就会迅速膨胀。因此选择合适的类库对Android开发者来说尤为重要。

开发者应该避免使用Google Guava这样的类库,它包含了13000多个方法。尽量使用专为移动应用设计的Lite/Android版本类库,或者使用小类库替换大类库,例如用Google-gson替换Jackson
JSON。而对于Google Protocol Buffers这样的数据交换格式,其标准实现会自动生成大量的方法。采用Square Wire的实现则可以很好地解决此问题。

Android应用打破65K方法数限制的更多相关文章

  1. Android应用解决65K方法数限制

    近日,Android Developers在Google+上宣布了新的Multidex支持库,为方法总数超过65K的Android应用提供了官方支持. 如果你是一名幸运的Android应用开发者,正在 ...

  2. Android方法数methods超过65536

    当Android App中的方法数超过65535时,如果往下兼容到低版本设备时,就会报编译错误: Cannot fit requested classes in a single dex file. ...

  3. 彻底解决Android 应用方法数不能超过65K的问题

    作为一名Android开发者,相信你对Android方法数不能超过65K的限制应该有所耳闻,随着应用程序功能不断的丰富,总有一天你会遇到一个异常: Conversion to Dalvik forma ...

  4. Android 65536方法数限制的思考

    前言 没想到,65536真的很小. 1 Unable to execute dex: method ID not in [0, 0xffff]: 65536 PS:本文只是纯探索一下这个65K的来源, ...

  5. Android查看应用方法数

    当一个项目快速迭代时,难免引进各种依赖,从而导致单个apk超过65k的限制.如何查询apk的方法数也是每个Android Developer必备技能. 我使用的是 dex-method-counts  ...

  6. [Android] Android统计Apk , jar包方法数

    reference to : http://www.jianshu.com/p/61e8f803e0d1 Android在开发过程中,随着引用的库以及业务的增多,不可避免的会出现64K limit问题 ...

  7. Android方法数不能超过65535

    为什么方法数不能超过65535?搬上Dalvik工程师在SF上的回答,因为在Dalvik指令集里,调用方法的invoke-kind指令中,method reference index只给了16bits ...

  8. Android 使用android-support-multidex解决Dex超出方法数的限制问题

    随着应用不断迭代,业务线的扩展,应用越来越大(比如集成了各种第三方sdk或者公共支持的jar包,项目耦合性高,重复作用的类越来越多),相信很多人都遇到过如下的错误: UNEXPECTED TOP-LE ...

  9. android MultiDex multidex原理下超出方法数的限制问题(三)

    android MultiDex 原理下超出方法数的限制问题(三)    插件化?自动化?multiDex?是不是觉得已经懵逼了?请先看这篇文章的内容,在下篇文章中将会详解具体的过程- 随着应用不断迭 ...

随机推荐

  1. hdu 4609 (FFT求解三角形)

    Problem Description King OMeGa catched three men who had been streaking in the street. Looking as id ...

  2. 基于 HTML5 的 WebGL 3D 智能楼宇监控系统

    前言 智能监控的领域已经涉及到了各大领域,工控.电信.电力.轨道交通.航天航空等等,为了减少人员的消耗,监控系统必不可少.之前我写过一篇 2D 的智能地铁监控系统广受好评,突然觉得,既然 2D 的这么 ...

  3. mvn package 和 mvn install

    刚刚准备将maven项目中一个子项目打个包,使用了mvn package.心想这个很简单嘛,没料就报错了.报错咱不怕,看看错在哪就好了. 编译出错,找不到我定义的异常类中的配置.那应该是引用父模块出来 ...

  4. js 数字前面自动补零

    num传入的数字,n需要的字符长度        function PrefixInteger(num, n) {            return (Array(n).join(0) + num) ...

  5. $.messager.confirm 用法

    <script type="text/javascript">     $(function () {         $.messager.defaults = { ...

  6. width:100vh有感而发

    在看一个网页的代码是看到 width:100vh  纳尼...这这我怎么没有见过,这是个什么属性,随之有看到 min-height:calc(100vh + 51px);这尼玛又是怎么用的.... 感 ...

  7. MySQL使用判断

    1.case语法 在第一个方案的返回结果中, value=compare-value.而第二个方案的返回结果是第一种情况的真实结果.如果没有匹配的结果值,则返回结果为ELSE后的结果,如果没有ELSE ...

  8. SQL注入原理及绕过安全狗

    1.什么是SQL注入攻击 SQL注入攻击指的是通过构造特殊的输入作为参数插入到Web表单的输入域或页面请求的查询字符串,欺骗服务器执行恶意的SQL命令 http://www.xxx.com/list. ...

  9. Jupyter Notebook

    Jupyter Notebook(此前被称为 IPython notebook)是一个交互式笔记本,支持运行 40 多种编程语言.在本文中,我们将介绍 Jupyter notebook 的主要特性,以 ...

  10. 学习ASP.NET Core Razor 编程系列七——修改列表页面

    学习ASP.NET Core Razor 编程系列目录 学习ASP.NET Core Razor 编程系列一 学习ASP.NET Core Razor 编程系列二——添加一个实体 学习ASP.NET ...