Android_65535問題的解決

來源:互聯網
上載者:User

標籤:格式   大量   對象   依賴   位元組   field   exec   guard   dal   

做過比較大的項目的人都知道,當app大到一定程度的時候,會出現65535這個錯誤,也就是64K,也就是,一個app包中,方法數不能超過65535個,超過了就要分成多個dex包,這個別問為什麼,android的限制。也可以理解為Android的一個"Bug"。

Eclipse的時代,要想解決這個問題,其實是很蛋疼的,但沒關係,現在有 Android Studio 了,這個問題就好解決了,官方也給出了確實的解決方案。

這裡,要分情況處理,以 Android5.0(Api:21)為分水嶺。

5.0以後要解決這個問題,其實很簡單

 minSdkVersion 21  targetSdkVersion 21 multiDexEnabled true

  只要是minSdkVersion 是21(或以上)的,就直接在 build.gradle 裡面添加多一個 multiDexEnabled true ,就在 minSdkVersion 所在的大括弧內添加就可以了。

但是,目前來說,國內還很多 4.X 的系統,所以,不得不要採取下面這種方式:

首先,添加庫支援

android {    defaultConfig {        ...        minSdkVersion 15         targetSdkVersion 26        multiDexEnabled true    }    ...}dependencies {  compile ‘com.android.support:multidex:1.0.1‘}

然後,編寫自己的  Application 類,並且讓它繼承自 MultiDexApplication

<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="com.example.myapp">    <application            android:name="android.support.multidex.MultiDexApplication" >        ...    </application></manifest>
public class MyApplication extends MultiDexApplication { ... }

如果,這一步,你無法實現,也就是說,你的 Application 已經繼承了其他的 Application 了,你可以這樣做:

public class MyApplication extends SomeOtherApplication {  @Override  protected void attachBaseContext(Context base) {     super.attachBaseContext(context);     Multidex.install(this);  }}

就這麼簡單,分兩步搞定,Android Studio 就是方便。

具體進一步的可以參考官方的。這是官方的原文(或者直接點擊上面的連結)。

配置方法數超過 64K 的應用隨著 Android 平台的持續成長,Android 應用的大小也在增加。當您的應用及其引用的庫達到特定大小時,您會遇到構建錯誤,指明您的應用已達到 Android 應用構建架構的極限。早期版本的構建系統按如下方式報告這一錯誤:Conversion to Dalvik format failed:Unable to execute dex: method ID not in [0, 0xffff]: 65536較新版本的 Android 構建系統雖然顯示的錯誤不同,但指示的是同一問題:trouble writing output:Too many field references: 131000; max is 65536.You may try using --multi-dex option.這些錯誤狀況都會顯示下面這個數字:65,536。這個數字很重要,因為它代表的是單個 Dalvik Executable (DEX) 位元組碼檔案內的代碼可調用的引用總數。本頁介紹如何通過啟用被稱為 Dalvik 可執行檔分包的應用配置來越過這一限制,使您的應用能夠構建並讀取 Dalvik 可執行檔分包 DEX 檔案。關於 64K 引用限制Android 應用 (APK) 檔案包含 Dalvik Executable (DEX) 檔案形式的可執行位元組碼檔案,其中包含用來運行您的應用的已編譯代碼。Dalvik Executable 規範將可在單個 DEX 檔案內可引用的方法總數限制在 65,536,其中包括 Android 架構方法、庫方法以及您自己代碼中的方法。在電腦科學領域內,術語千(簡稱 K)表示 1024(或 2^10)。由於 65,536 等於 64 X 1024,因此這一限制也稱為“64K 引用限制”。Android 5.0 之前版本的 Dalvik 可執行檔分包支援Android 5.0(API 層級 21)之前的平台版本使用 Dalvik 運行時來執行應用代碼。預設情況下,Dalvik 限制應用的每個 APK 只能使用單個 classes.dex 位元組碼檔案。要想繞過這一限制,您可以使用 Dalvik 可執行檔分包支援庫,它會成為您的應用主要 DEX 檔案的一部分,然後管理對其他 DEX 檔案及其所包含代碼的訪問。註:如果您的項目配置時所面向的 Dalvik 可執行檔分包使用的是 minSdkVersion 20 或更低版本,並且您將其部署到運行 Android 4.4(API 層級 20)或更低版本的目標裝置上,則 Android Studio 會停用 Instant Run。Android 5.0 及更高版本的 Dalvik 可執行檔分包支援Android 5.0(API 層級 21)及更高版本使用名為 ART 的運行時,後者原生支援從 APK 檔案載入多個 DEX 檔案。ART 在應用安裝時執行先行編譯,掃描 classesN.dex 檔案,並將它們編譯成單個 .oat 檔案,供 Android 裝置執行。因此,如果您的 minSdkVersion 為 21 或更高值,則不需要 Dalvik 可執行檔分包支援庫。如需瞭解有關 Android 5.0 運行時的詳細資料,請參閱 ART 和 Dalvik。註:如果將應用的 minSdkVersion 設定為 21 或更高值,使用 Instant Run 時,Android Studio 會自動將應用配置為進行 Dalvik 可執行檔分包。由於 Instant Run 僅適用於調試版本的應用,您仍需配置發布構建進行 Dalvik 可執行檔分包,以規避 64K 限制。規避 64K 限制在將您的應用配置為支援使用 64K 或更多方法引用之前,您應該採取措施減少應用代碼調用的引用總數,包括由您的應用代碼或包含的庫定義的方法。下列策略可協助您避免達到 DEX 引用限制:檢查您的應用的直接和傳遞依賴項 - 確保您在應用中使用任何龐大依賴庫所帶來的好處大於為應用添加大量代碼所帶來的弊端。一種常見的反面模式是,僅僅為了使用幾個實用方法就在應用中加入非常龐大的庫。減少您的應用代碼依賴項往往能夠協助您規避 dex 引用限制。通過 ProGuard 移除未使用的代碼 - 為您的版本構建啟用代碼壓縮以運行 ProGuard。啟用壓縮可確保您交付的 APK 不含有未使用的代碼。使用這些技巧使您不必在應用中啟用 Dalvik 可執行檔分包,同時還會減小 APK 的總體大小。配置您的應用進行 Dalvik 可執行檔分包將您的應用項目設定為使用 Dalvik 可執行檔分包配置需要對您的應用項目進行以下修改,具體取決於應用支援的最低 Android 版本。如果您的 minSdkVersion 設定為 21 或更高值,您只需在模組層級 build.gradle 檔案中將 multiDexEnabled 設定為 true,如此處所示:android {    defaultConfig {        ...        minSdkVersion 21         targetSdkVersion 26        multiDexEnabled true    }    ...}但是,如果您的 minSdkVersion 設定為 20 或更低值,則您必須按如下方式使用 Dalvik 可執行檔分包支援庫:修改模組層級 build.gradle 檔案以啟用 Dalvik 可執行檔分包,並將 Dalvik 可執行檔分包庫添加為依賴項,如此處所示:android {    defaultConfig {        ...        minSdkVersion 15         targetSdkVersion 26        multiDexEnabled true    }    ...}dependencies {  compile ‘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">    <application            android:name="android.support.multidex.MultiDexApplication" >        ...    </application></manifest>如果您替換了 Application 類,請按如下方式對其變更以擴充 MultiDexApplication(如果可能):public class MyApplication extends MultiDexApplication { ... }或者,如果您替換了 Application 類,但無法更改基本類,則可以改為替換 attachBaseContext() 方法並調用 MultiDex.install(this) 來啟用 Dalvik 可執行檔分包:public class MyApplication extends SomeOtherApplication {  @Override  protected void attachBaseContext(Context base) {     super.attachBaseContext(context);     Multidex.install(this);  }}構建應用後,Android 構建工具會根據需要構建主 DEX 檔案 (classes.dex) 和輔助 DEX 檔案(classes2.dex 和 classes3.dex 等)。然後,構建系統會將所有 DEX 檔案打包到您的 APK 中。運行時,Dalvik 可執行檔分包 API 使用特殊的類載入器來搜尋適用於您的方法的所有 DEX 檔案(而不是僅在主 classes.dex 檔案中搜尋)。Dalvik 可執行檔分包支援庫的局限性Dalvik 可執行檔分包支援庫具有一些已知的局限性,將其納入您的應用構建配置之中時,您應該注意這些局限性並進行針對性的測試:啟動期間在裝置資料分區中安裝 DEX 檔案的過程相當複雜,如果輔助 DEX 檔案較大,可能會導致應用無響應 (ANR) 錯誤。在此情況下,您應該通過 ProGuard 應用代碼壓縮以盡量減小 DEX 檔案的大小,並移除未使用的那部分代碼。由於存在 Dalvik linearAlloc 錯誤(問題 22586),使用 Dalvik 可執行檔分包的應用可能無法在啟動並執行平台版本早於 Android 4.0(API 層級 14)的裝置上啟動。如果您的目標 API 層級低於 14,請務必針對這些版本的平台進行測試,因為您的應用可能會在啟動時或載入特定類群時出現問題。代碼壓縮可以減少甚至有可能消除這些潛在問題。由於存在 Dalvik linearAlloc 限制(問題 78035),因此,如果使用 Dalvik 可執行檔分包配置的應用發出非常龐大的記憶體配置請求,則可能會在運行期間發生崩潰。儘管 Android 4.0(API 層級 14)提高了分配限制,但在 Android 5.0(API 層級 21)之前的 Android 版本上,應用仍有可能遭遇這一限制。聲明主 DEX 檔案中需要的類為 Dalvik 可執行檔分包構建每個 DEX 檔案時,構建工具會執行複雜的決策制定來確定主要 DEX 檔案中需要的類,以便應用能夠成功啟動。如果啟動期間需要的任何類未在主 DEX 檔案中提供,那麼您的應用將崩潰並出現錯誤 java.lang.NoClassDefFoundError。該情況不應出現在直接從應用代碼訪問的代碼上,因為構建工具能識別這些代碼路徑,但可能在代碼路徑可見度較低(如使用的庫具有複雜的依賴項)時出現。例如,如果代碼使用自檢機制或從原生代碼調用 Java 方法,那麼這些類可能不會被識別為主 DEX 檔案中的必需項。因此,如果您收到 java.lang.NoClassDefFoundError,則必須使用構建類型中的 multiDexKeepFile 或 multiDexKeepProguard 屬性聲明它們,以手動將這些其他類指定為主 DEX 檔案中的必需項。如果類在 multiDexKeepFile 或 multiDexKeepProguard 檔案中匹配,則該類會添加至主 DEX 檔案。multiDexKeepFile 屬性您在 multiDexKeepFile 中指定的檔案應該每行包含一個類,並且採用 com/example/MyClass.class 的格式。例如,您可以建立一個名為 multidex-config.txt 的檔案,如下所示:com/example/MyClass.classcom/example/MyOtherClass.class然後,您可以按以下方式針對構建型別宣告該檔案:android {    buildTypes {        release {            multiDexKeepFile file ‘multidex-config.txt‘            ...        }    }}請記住,Gradle 會讀取相對於 build.gradle 檔案的路徑,因此如果 multidex-config.txt 與 build.gradle 檔案在同一目錄中,以上樣本將有效。multiDexKeepProguard 屬性multiDexKeepProguard 檔案使用與 Proguard 相同的格式,並且支援整個 Proguard 文法。如需瞭解有關 Proguard 格式和文法的詳細資料,請參閱 Proguard 手冊中的 Keep Options 一節。您在 multiDexKeepProguard 中指定的檔案應該在任何有效 ProGuard 文法中包含 -keep 選項。例如,-keep com.example.MyClass.class。您可以建立一個名為 multidex-config.pro 的檔案,如下所示:-keep class com.example.MyClass-keep class com.example.MyClassToo如果您想要指定包中的所有類,檔案將如下所示:-keep class com.example.** { *; } // All classes in the com.example package然後,您可以按以下方式針對構建型別宣告該檔案:android {    buildTypes {        release {            multiDexKeepProguard ‘multidex-config.pro‘            ...        }    }}最佳化開發構建中的 Dalvik 可執行檔分包Dalvik 可執行檔分包配置會大幅增加構建處理時間,因為構建系統必須就哪些類必須包括在主 DEX 檔案中以及哪些類可以包括在輔助 DEX 檔案中作出複雜的決策。這意味著使用 Dalvik 可執行檔分包的增量式構建通常耗時更長,可能會拖慢您的開發進度。為了縮短耗時更長的 Dalvik 可執行檔分包輸出構建時間,請利用 productFlavors(一個開發定製和一個發布定製,具有不同的 minSdkVersion 值)建立兩個構建變型。對於開發定製,將 minSdkVersion 設定為 21。該設定將啟用一個名為 pre-dexing 的構建功能,此功能使用僅適用於 Android 5.0(API 層級 21)和更高版本的 ART 格式更快產生 Dalvik 可執行檔分包輸出。對於發布定製,將 minSdkVersion 設定為適於您的實際最低支援層級。此設定產生的 Dalvik 可執行檔分包 APK 可相容更多裝置,但構建時間更長。以下構建配置樣本展示了如何在 Gradle 構建檔案中設定這些定製:android {    defaultConfig {        ...        multiDexEnabled true    }    productFlavors {        dev {            // Enable pre-dexing to produce an APK that can be tested on            // Android 5.0+ without the time-consuming DEX build processes.            minSdkVersion 21        }        prod {            // The actual minSdkVersion for the production version.            minSdkVersion 14        }    }    buildTypes {        release {            minifyEnabled true            proguardFiles getDefaultProguardFile(‘proguard-android.txt‘),                                                 ‘proguard-rules.pro‘        }    }}dependencies {    compile ‘com.android.support:multidex:1.0.1‘}您完成此配置變更後,可以為增量式構建使用應用的 devDebug 變體,後者集 dev 產品定製與 debug 構建類型的屬性於一身。這將建立已啟用 Dalvik 可執行檔分包且禁用 proguard 的可調試應用(因為 minifyEnabled 預設為 false)。這些設定會使適用於 Gradle 的 Android 外掛程式執行以下操作:執行 pre-dexing:將每個應用模組和每個依賴項構建為單獨的 DEX 檔案。將每個 DEX 檔案加入 APK,並且不做任何修改(不執行代碼壓縮)。最重要的是,模組 DEX 檔案不執行合併作業,因此可以避免為確定主 DEX 檔案的內容而進行長時間的計算。這些設定的好處是,可以進行快速的增量式構建,因為只有修改過的模組的 DEX 檔案才會在後續構建期間重新計算並重新打包。但是,這些構建的 APK 只能用於在 Android 5.0 裝置上進行測試。不過,由於是以定製形式實現配置,您保留了使用與發布相適的最低 API 層級和 ProGuard 代碼壓縮執行正常構建的能力。您還可以構建其他變體,包括 prodDebug 變體構建,該變體雖然構建時間更長,但可用於開發以外的測試。在所示配置內,prodRelease 變體將是最終測試和發布版本。如需瞭解有關使用構建變體的詳細資料,請參閱配置構建變體。提示:由於您有適用於不同 Dalvik 可執行檔分包需求的不同構建變體,因此也可以為不同變體提供不同資訊清單檔(這樣,只有適用於 API 層級 20 和更低版本的資訊清單檔會更改 <application> 標記名稱),或者為每個變體建立不同的 Application 子類(這樣,只有適用於 API 層級 20 和更低版本的資訊清單檔會擴充 MultiDexApplication 類或調用 MultiDex.install(this))。測試 Dalvik 可執行檔分包應用編寫面向 Dalvik 可執行檔分包應用的儀器測試時,無需進行其他配置。AndroidJUnitRunner 直接支援 Dalvik 可執行檔分包,前提是您使用 MultiDexApplication 或替換您的自訂 Application 對象中的 attachBaseContext() 方法,並調用 MultiDex.install(this) 以啟用 Dalvik 可執行檔分包。或者,您可以替換 AndroidJUnitRunner 中的 onCreate() 方法:public void onCreate(Bundle arguments) {    MultiDex.install(getTargetContext());    super.onCreate(arguments);    ...}註:目前不支援使用 Dalvik 可執行檔分包來建立測試 APK。

  

 

Android_65535問題的解決

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.