Android應用打破65K方法數限制

近日,Android Developers在Google+上宣佈了新的Multidex支持庫,爲方法總數超過65K的Android應用提供了官方支持。 html

若是你是一名幸運的Android應用開發者,正在開發一個前景廣闊的應用,不斷地加入新功能、添加新的類庫,那麼終有一天,你會不幸遇到這個錯誤: android

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

這個錯誤是Android應用的方法總數限制形成的。Android平臺的Java虛擬機Dalvik在執行DEX格式的Java應用程序時,使用原生類型short來索引DEX文件中的方法。這意味着單個DEX文件可被引用的方法總數被限制爲65536。一般APK包含一個classes.dex文件,所以Android應用的方法總數不能超過這個數量,這包括Android框架、類庫和你本身開發的代碼。 github

這個問題能夠經過將一個DEX文件分拆成多個DEX文件解決。Facebook介紹了爲Android應用開發的Dalvik補丁;Android Developers博客介紹了經過自定義類加載過程的方法來解決此問題。但這些方法有些複雜並且並不優雅。 app

隨着新的MultiDex支持庫發佈,Google正式爲解決此問題提供官方支持。構建超過65K方法數的應用介紹瞭如何使用Gradle構建多DEX應用。 框架

首先使用Android SDK Manager升級到最新的Android SDK Build Tools和Android Support Library R21。而後進行如下兩步操做: ide

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文件的訪問。 ui

文中還介紹了在開發多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多個方

相關文章
相關標籤/搜索