(配置超過64K方法的應用程序)com.android.dex.DexIndexOverflowException: method ID not in [0, 0xffff]: 65536

這是谷歌官方的解釋:(翻譯過來的)
原文地址(需要翻牆):
https://developer.android.com/studio/build/multidex.html
導致異常以及主要原因(藍色標記)以及解決方法(紅色標記)
Error:Execution failed for task ':app:transformClassesWithDexForDebug'.
> com.android.build.api.transform.TransformException: com.android.ide.common.process.ProcessException: java.util.concurrent.ExecutionException: com.android.dex.DexIndexOverflowException: method ID not in [0, 0xffff]: 65536
配置超過64K方法的應用程序

隨着Android平臺不斷增長,Android應用程序的規模也在不斷增加。當您的應用程式及其參照的程式庫達到一定大小時,您會遇到建立錯誤,指出您的應用程式已達到Android應用程式建置架構的上限。早期版本的構建系統報告此錯誤如下:
轉換爲Dalvik格式失敗:
無法執行dex:方法ID不在[0,0xffff]:65536
更多最新版本的Android構建系統顯示不同的錯誤,這是同樣問題的指示:
故障寫輸出:
太多字段引用:131000;最大爲65536。
您可以嘗試使用--multi-dex選項。
這兩個錯誤條件都顯示一個常用的數字:65,536。這個數字很重要,因爲它代表單個Dalvik可執行文件(DEX)字節碼文件中的代碼可以調用的引用的總數。本頁說明如何通過啓用稱爲multidex的應用程序配置來超越此限制,允許您的應用程序構建和讀取多個DEX文件。
關於64K引用limitAndroid應用程序(APK)文件包含Dalvik可執行文件(DEX)形式的可執行字節碼文件,它包含用於運行應用程序的編譯代碼。 Dalvik Executable規範將單個DEX文件中可以引用的方法的總數限制爲65,536!包括Android框架方法,庫方法和您自己的代碼中的方法。在計算機科學的上下文中,術語Kilo,K表示1024(或2 ^ 10)。因爲65,536等於64 X 1024,所以此限制稱爲“64K參考限制”。
在Android 5.0之前的Android 5.0版本(API級別21)之前的Multidex支持使用Dalvik運行時來執行應用程序代碼。默認情況下,Dalvik將應用程序限制爲每個APK一個singleclasses.dex字節碼文件。爲了克服這個限制,您可以使用multidex支持庫,它成爲應用程序的主要DEX文件的一部分,然後管理對其他DEX文件及其包含的代碼的訪問。
注意:如果您的項目配置爲使用minSdkVersion 20或更低版本的multidex,並且部署到運行Android 4.4(API級別20)或更低版本的目標設備,Android Studio將禁用即時運行。
Multidex支持Android 5.0和更高版本Android 21和更高版本使用一個運行時稱爲ART本身支持從APK文件加載多個DEX文件。 ART在應用安裝時執行預編譯,掃描classesN.dex文件並將其編譯爲單個.oat文件以供Android設備執行。因此,如果您的minSdkVersion爲21或更高版本,則不需要multidex支持庫。
有關Android 5.0運行時的更多信息,請閱讀ART和Dalvik。
注意:使用即時運行時,Android Studio會自動將您的應用程序配置爲multidex,當您的應用程序的minSdkVersion設置爲21或更高。因爲即時運行只適用於您的應用程序的調試版本,所以您仍然需要配置multidex的發行版本以避免64K限制。
避免64K限制在配置應用程序以啓用使用64K或更多方法引用之前,您應該採取措施減少應用程序代碼調用的引用總數,包括由應用程序代碼或包含的庫定義的方法。以下策略可幫助您避免達到DEX參考限值:

*檢查應用程序的直接和傳遞依賴關係 - 確保在應用程序中包含的任何大型庫依賴關係的使用方式大於添加到應用程序的代碼量。一個常見的反模式是包含一個非常大的庫,因爲一些實用的方法是有用的。減少應用程序代碼依賴關係通常可以幫助您避免DEX引用限制。
*使用ProGuard刪除未使用的代碼 - 啓用代碼縮小,以便爲您的發佈版本運行ProGuard。啓用縮小功能可確保您不會使用APK傳送未使用的代碼。

使用這些技術可能會幫助您避免在應用程序中啓用multidex,同時還會減少APK的總體大小。
爲multidex配置應用程序設置應用項目以使用multidex配置要求您對應用項目進行以下修改,具體取決於您的應用支持的最低Android版本。
如果你的minSdkVersion設置爲21或更高,所有你需要做的是在模塊級build.gradle文件中將multiDexEnabled設置爲true,如下所示:
android {
    defaultConfig {
        ... ...
        minSdkVersion 21
        targetSdkVersion 25
        multiDexEnabled true
    }}
    ... ...
}}
但是,如果您的minSdkVersion設置爲20或更低,那麼必須使用multidex支持庫,如下所示:

*修改模塊級build.gradle文件以啓用multidex並將multidex庫添加爲依賴關係,如下所示:
android {
    defaultConfig {
        ... ...
        minSdkVersion 15
        targetSdkVersion 25
        multiDexEnabled true
    }}
    ... ...
}}

依賴關係{
  編譯'com.android.support:multidex:1.0.1'
}}

*根據是否覆蓋Application類,請執行以下操作之一:
*:
*如果不覆蓋Application類,請編輯清單文件以在<application>標記中設置android:name,如下所示:
<?xml version =“1.0”encoding =“utf-8”?>
<manifest xmlns:android =“http://schemas.android.com/apk/res/android”
    package =“com.example.myapp”>
    <應用程序
            android:name =“android.support.multidex.MultiDexApplication”>
        ... ...
    </ application>
</ manifest>

*如果您覆蓋Application類,請將其更改爲擴展MultiDexApplication(如果可能),如下所示:
public class MyApplication extends MultiDexApplication {...}

*或者如果你重寫了Application類,但是不可能改變基類,那麼你可以重寫attachBaseContext()方法並調用MultiDex.install(this)來啓用multidex:
public class MyApplication extends SomeOtherApplication {
  @覆蓋
  protected void attachBaseContext(Context base){
     super.attachBaseContext(context);
     Multidex.install(this);
  }}
}}



現在當你構建你的應用程序,Android構建工具構建一個主要的DEX文件(classes.dex)和支持DEX文件(classes2.dex,classes3.dex,等等)根據需要。構建系統然後將所有DEX文件打包到您的APK。
在運行時,multidex API使用特殊的類加載器來搜索您的方法的所有可用DEX文件(而不是僅在mainclasses.dex文件中搜索)。
multidex支持庫的限制multidex支持庫有一些已知的限制,您應該注意並測試何時將它合併到您的應用程序構建配置:

*在啓動過程中將DEX文件安裝到設備的數據分區上很複雜,如果輔助DEX文件較大,可能導致應用程序無響應(ANR)錯誤。在這種情況下,您應該使用ProGuard應用縮減代碼以最小化DEX文件的大小並刪除未使用的代碼部分。
*由於Dalvik linearAlloc錯誤(問題22586),使用multidex的應用程序可能無法在運行低於Android 4.0(API級別14)的平臺的設備上啓動。如果您的API級別低於14,請務必使用這些版本的平臺進行測試,因爲您的應用在啓動時或加載特定類別的組時可能會遇到問題。代碼縮減可以減少或可能消除這些潛在問題。
*由於Dalvik linearAlloc限制(Issue78035),使用multidex配置進行非常大的內存分配請求的應用程序可能在運行時崩潰。 Android 4.0(API級別14)中的分配限制已增加,但在Android 5.0(API級別21)之前的Android版本中,應用仍可能達到此限制。

聲明主DEX文件中所需的類在構建multidex應用程序的每個DEX文件時,構建工具執行復雜的決策,以確定主DEX文件中需要哪些類,以便您的應用程序可以成功啓動。如果在初始DEX文件中沒有提供啓動期間所需的任何類,那麼您的應用程序會崩潰,並返回錯誤java.lang.NoClassDefFoundError。
這不應該發生在直接從應用程序代碼訪問的代碼上,因爲構建工具會識別這些代碼路徑,但是當代碼路徑不太明顯時,例如當您使用的庫具有複雜的依賴關係時,就會發生這種情況。例如,如果代碼使用內省或從本機代碼調用Java方法,那麼這些類可能不會被識別爲主DEX文件中的必需。
因此,如果您收到java.lang.NoClassDefFoundError,那麼必須在生成類型中使用multiDexKeepFile屬性聲明它們,從而在主DEX文件中手動指定這些附加類。您在此處指定的文件應該在每行中包含一個類,在formatcom / example / MyClass.class中。例如,您可以創建一個名爲dex.keep的文件,如下所示:
com / example / MyClass.class
com / example / MyOtherClass.class
然後,您可以如下爲生成類型聲明該文件:
android {
    buildTypes {
        發佈 {
            multiDexKeepFile文件('dex.keep')
            ... ...
        }}
    }}
}}
記住,Gradle讀取相對於build.gradle的路徑,因此如果dex.keep與build.gradle文件在同一目錄中,上面的示例工作。
在開發構建中優化multidex multidex配置需要顯着增加構建處理時間,因爲構建系統必須做出關於哪些類必須包含在主DEX文件中以及哪些類可以包含在輔助DEX文件中的複雜決策。這意味着使用multidex的增量構建通常需要更長的時間,並且可能會減慢您的開發過程。
要減少multidex輸出的較長構建時間,請使用productFlavors創建兩個構建變體:一個開發風格和一個具有不同minSdkVersion值的發佈風格。
對於開發風格,將minSdkVersion設置爲21.此設置啓用稱爲預先dexing的構建功能,使用僅適用於Android 5.0(API級別21)或更高版本的ART格式,可以更快地生成multidex輸出。對於發行版本,請將minSdkVersion設置爲適合您實際的最低支持級別。此設置會生成與更多設備兼容的multidex APK,但需要更長時間才能生成。
以下構建配置示例演示如何在Gradle構建文件中設置這些類型:
android {
    defaultConfig {
        ... ...
        multiDexEnabled true
    }}
    產品簡介{
        dev {
            //啓用pre dexing產生一個可以測試的APK
            // Android 5.0+,沒有耗時的DEX構建過程。
            minSdkVersion 21
        }}
        prod {
            //生產版本的實際minSdkVersion。
            minSdkVersion 14
        }}
    }}
    buildTypes {
        發佈 {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'),
                                                 'proguard-rules.pro'
        }}
    }}
}}
依賴關係{
    編譯'com.android.support:multidex:1.0.1'
}}
完成此配置更改後,可以使用應用程序的devDebug變量進行增量構建,其中結合了thedev產品flavor和調試構建類型的屬性。這創建一個可調試的應用程序,啓用multidex和proguard禁用(因爲minifyEnabled isfalse默認情況下)。這些設置導致Gradle的Android插件執行以下操作:

1.執行pre dexing:將每個應用程序模塊和每個依賴項構建爲單獨的DEX文件。
2.在APK中包含每個DEX文件,不進行修改(沒有縮小代碼)。
最重要的是,模塊DEX文件不組合,因此避免了長時間運行的計算以確定主DEX文件的內容。

這些設置導致快速增量構建,因爲在後續構建期間只重新計算並重新打包修改模塊的DEX文件。但是,來自這些版本的APK只能用於在Android 5.0設備上測試。但是,通過將配置實現爲一種風格,您可以保留使用適當的最低API級別和ProGuard代碼收縮執行正常構建的能力。
您還可以構建其他變體,包括prodDebug變體生成,這需要更長的構建,但可以用於在開發外測試。在所示的配置中,prodRelease變量將是最終測試和發行版本。有關使用構建變體的詳細信息,請參閱配置構建變體。
提示:現在您針對不同的multidex需求有不同的構建版本,您還可以爲每個版本提供不同的清單文件(因此只有針對API級別20和更低版本的版本更改了<application>標記名稱),或者創建不同的應用程序子類(所以只有一個爲API級別20和更低版本擴展MultiDexApplication類或調用MultiDex.install(this))。
測試multidex應用程序在爲multidex應用程序編寫測試測試時,不需要其他配置。 AndroidJUnitRunner支持multidex開箱即用,只要在自定義Application對象中使用MultiDexApplication或覆蓋attachBaseContext()方法,並調用MultiDex.install(this)以啓用multidex。
或者,您可以覆蓋AndroidJUnitRunner中的onCreate()方法:
public void onCreate(Bundle arguments){
    MultiDex.install(getTargetContext());
    super.onCreate(arguments);
    ... ...
}}

注意:目前不支持使用multidex創建測試APK。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章