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.updateIndex(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種選擇:
-
如果你沒有創建自己的Application 類,在你的清單文件AndroidManifest.xml中配置android.support.multidex.MultiDexApplication就可以了。
.... android:name="android.support.multidex.MultiDexApplication" ...
- 如果你有自己的Application類了,讓它繼承 android.support.multidex.MultiDexApplication而不是android.app.Application
-
如果你的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文件讓你可以在設備或者模擬器上運行。
你可以從這個項目看到上面的效果
注意事項
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混淆,如果你必須要使用這個方案。請確保在舊設備上做了測試。
版權聲明:本文為博主原創文章,未經博主允許不得轉載。