1. 程式人生 > >DEX 方法超過64K限制和gradle編譯OOM問題解決

DEX 方法超過64K限制和gradle編譯OOM問題解決

如果你是一個android開發者,你至少聽說過的Dalvik的蛋疼的64K方法限制。概括地說,在一個DEX檔案,你可以呼叫很多的方法,但你只能呼叫它們最前面的65,536個 ,因為這是在方法呼叫集合中的所有的空間了。如果你的原始碼和狂拽炫酷叼炸天的三方庫中方法超過了這個限制。看這篇文章就對了。

UNEXPECTED TOP-LEVEL EXCEPTION: com.android.dex.DexIndexOverflowException: method ID not in [0, 0xffff]: 65536 at com.android.dx.merge.DexMerger$6.update

Index(DexMerger.Java:502) at com.android.dx.merge.DexMerger$IdMerger.mergeSorted(DexMerger.java:277) at com.android.dx.merge.DexMerger.mergeMethodIds(DexMerger.java:491) at com.android.dx.merge.DexMerger.mergeDexes(DexMerger.java:168) at com.android.dx.merge.DexMerger.merge(DexMerger.java:189) at com.android.dx.
command
.dexer.Main.mergeLibraryDexBuffers(Main.java:454) at com.android.dx.command.dexer.Main.runMonoDex(Main.java:302) at com.android.dx.command.dexer.Main.run(Main.java:245) at com.android.dx.command.dexer.Main.main(Main.java:214) at com.android.dx.command.Main.main(Main.java:106)

點此檢視更多相關話題

為了解決這個問題,Android開發社群有人想出了一些

解決方案,比如dmarcato的這個,還有casidiablo的這個。他們都是可行的,但是需要一些比較嚴格的條件。

最終,Google決定提供一套官方的解決方案,在10月14日的時候釋出了MultiDex 支援庫,隨後幾周gradle在 v0.14.0版本中也支援了。

使用MultiDex支援庫

如果你在使用 Android Studio,這個用起來很簡單。如果不是,強烈建議你遷移過來。因為Google很快就會不知處Eclipse外掛和舊的基於Ant的系統構建方式。

第1步 
新增依賴於你的build.gradle支援MultiDex庫

dependencies { ... compile 'com.android.support:multidex:' ... }

第2步 
在buildType或productFlavor中開啟multiDexEnabled。

defaultConfig { ... multiDexEnabled true ... }

現在,根據你的專案情況,你有3種選擇:

  1. 如果你沒有建立自己的Application 類,在你的清單檔案AndroidManifest.xml中配置android.support.multidex.MultiDexApplication就可以了。

    .... android:name="android.support.multidex.MultiDexApplication" ...

  2. 如果你有自己的Application類了,讓它繼承 android.support.multidex.MultiDexApplication而不是android.app.Application
  3. 如果你的Application繼承了其他的類,並且你不想改變或者沒辦法改變。按照下面的方法重寫attachBaseContext()

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

不論你選擇上面哪種,都會建立多個大小差不多的dex檔案代替單個龐大的dex檔案。執行的時候回同事載入所有的這些dex檔案。

當年編譯app的時候,Gradle會生成很多個dex檔案和一個apk檔案讓你可以在裝置或者模擬器上執行。

enter image description here
你可以從這個專案看到上面的效果

注意事項

Out of memory 問題 
對於有很多依賴的專案,編譯可能因為下面的錯誤中斷

Error:Execution failed for task ':app:dexDebug'. ... Error Code: 3 Output: UNEXPECTED TOP-LEVEL ERROR: java.lang.OutOfMemoryError: GC overhead limit exceeded at com.android.dx.cf.cst.ConstantPoolParser.parse0(ConstantPoolParser.java:326) ...

在build.gralde android標籤下面新增下面程式碼可以解決

dexOptions { incremental true javaMaxHeapSize "4g" }

應用啟動緩慢 
根據我們的經驗,添加了這個支援庫以後,大多數情況下都正常了。這對某些裝置,比如Kindle Fire上面,應用啟動會比之前慢很多。載入所有的類在應用一啟動的時候會花費大量的時間。這就會導致黑屏一段時間,甚至導致ANR.

更多推薦方案點選這裡

結論

這個雖然在大多數時候可以解決DEX 64K的問題,但是應該是保留使用。當你嘗試使用它以前,請先嚐試刪除不需要的依賴並且使用ProGuard混淆,如果你必須要使用這個方案。請確保在舊裝置上做了測試。