關於 Android Dex 方法限制的一些總結
本文轉載自:http://greenrobot.me/devpost/about-android-dex-method-number-limit/
Android的編譯過程
在瞭解這個問題之前我們先要來看看Android 應用編譯的過程:
-
IDE中的資源打包工具 (Android Asset Packaging Tool ,即圖中的aapt) 會將應用中的資源文件進行編譯,這些資源文件包括
AndroidManifest.xml
文件,爲Activity定義的 XML 文件等等。在這個編譯過程中也會產生一個R.java
文件,這樣你就可以在你的Java代碼中引用這些資源了。 -
aidl 工具會將你項目中的所有
.aidl
接口轉換成Java接口。 -
項目中的所有的Java代碼,包括
R.java
和.aidl
文件,都會被Java編譯器編譯,然後輸出 .class 文件。 -
接着 dex 工具就會把上一步驟產生的 .class 文件轉成 Dalvik 字節碼,也就是
.dex
文件。同時項目中包含的所有第三方類庫和 .class 文件也會被轉換成.dex
文件,這樣講方便下一步被打包成最終的.apk
文件。 -
所有的不能編譯的資源(比如圖片等等)、編譯後的資源文件和 .dex 文件會被 apkbuilder 工具打包成一個
.apk
文件。 -
一旦
.apk
文件被構建好之後,如果要把把它安裝到設備上面去的話,它就必須用一個debug 或者發行key來對這個apk文件簽名。 -
最後,如果應用程序已經被簽名成爲發行模式的apk,你還需要使用 aipalign工具對
.apk
進行對齊優化。這樣的話可以減少應用程序在設備上的內存消耗。
爲什麼會有這個Dex方法限制
內部原因:
我們注意到在第四步的時候,會產生一個.dex
文件。Android 從之前的Dalvik 到現在Android 5.0 默認的ART 運行時環境都能夠執行這個.dex
文件,它們還使用同一套指令集,即Dalvik 指令集。通過這篇關於Android
指令集格式的介紹文章中,我可以知道Dalvik 指令集是使用16位寄存器來保存項目中所有的方法引用,包括第三方的方法:
這就意味着 Android的單個.dex
文件最能引用65536個方法,在這之後的方法就無法引用了。這就是Android
Dex 方法限制異常出現的原因,同時因爲ART和Dalvik使用同一套指令集,這個限制在ART 運行時環境中也會存在。
外部原因:
第三方庫裏面包含太多的方法。這裏就拿Google Play Service和Guava來舉例。很多Android開發者都會用到Google Play Service庫和Guava庫,而你知道它們提供了多少了方法嗎?Google Play Service 5.0裏面就差不多包含了將近20k+方法,Guava提供了將近14k個方法。這個兩個庫就將近佔了方法限制數目65536的半壁江山。
那麼如何解決Android Dex 方法限制這個問題呢?
老方法
對於內部原因:
-
從上面的描述中我們知道,Android Dex 方法限制是出現在單個
.dex
文件中的,那麼我們可以在一個apk中使用多個.dex
文件嗎?可以,Android 官方博客就給出了這個方案。(在Android5.0之前,由於大部分使用的是Dalvik 運行時環境,Dalvik 運行時環境限制一個apk只能包含一個classes.dex文件。)
對於外部原因:
新方法(官方動作)
主要思路:使用multidex
support library 讓Android5.0之前的版本也能在一個apk裏面包含多個.dex
文件。具體使用方法請參看這篇文章。
Google不僅在工具上面做出了改進,還把自己的Google Play Service庫也做了一番改動——從Google Play Service 6.5開始開始支持更細精度的依賴管理,也就是說你只需要Google Drive的api,而不需要google game,maps或者wallet等api的支持,那你就可以只引入Google Drive的api即可。這樣可以在很大程度上減少Dex 方法限制出現的機率。
參考鏈接:
- http://developer.android.com/tools/building/index.html
- http://android-developers.blogspot.com/2011/07/custom-class-loading-in-dalvik.html
- https://medium.com/@rotxed/dex-skys-the-limit-no-65k-methods-is-28e6cb40cf71
- http://developer.android.com/tools/building/multidex.html
- jakewharton.com/play-services-is-a-monolith/
- http://www.keysolutions.com/blogs/kenyee.nsf/d6plinks/KKYE-9LP5ND
- http://www.alittlemadness.com/2010/06/07/understanding-the-android-build-process/
- http://source.android.com/devices/tech/dalvik/dalvik-bytecode.html
- http://stackoverflow.com/questions/21490382/does-the-android-art-runtime-have-the-same-method-limit-limitations-as-dalvik/21492160#21492160
- https://android.googlesource.com/platform/dalvik/+/froyo/vm/analysis/ReduceConstants.c