您好,登錄后才能下訂單哦!
本篇內容介紹了“dex優化對Arouter查找路徑有什么影響”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
一、前言
1.1 APK的編譯和打包流程
1.2 dex文件的應用場景
二、dex到vdex、odex
2.1 ART預優化
2.2 ART的運行方式
2.3 vdex、odex的作用
2.4 vdex、odex與classes.dex關系
三、Arouter是什么
四、踩坑
4.1 現象
4.2 解決方案
五、總結
疑問:dex文件是什么?dex文件優化又是什么?
dex文件優化會給項目帶來什么問題,怎么解決這些問題?
1、通過aapt打包資源文件res,對應生成R.java、resources.arsc和res文件(二進制&非二進制保持原來的代碼)
2、處理aidl文件,生成java接口文件(沒有aidl則忽略)
3、通過java compile編譯R.java、java接口文件,生成對應.class文件(java compiler)
4、運用dex命令,將.class文件和第三方sdk庫中的.class文件轉換成classes.dex文件
5、通過apkbuilder將aapt生成的CompiledResources和其他資源文件以及classes.dex文件打包生成apk
6、同樣的,可以使用Jarsigner工具,對上面的apk進行debug或者release簽名
apk的編譯和打包流程圖如下:
實際項目開發中,5、6兩個步驟,可以借助jenkins平臺直接生成release包即可滿足需求。
再來看看dex文件常用的場景,比較流行的有:APK 的瘦身、熱修復、插件化、應用加固、Android 逆向工程、64 K 方法數限制。
拿方法數限制舉例,在上面的第4步,將class文件轉換成dex文件,默認只會生成一個dex文件,單個dex文件中的方法數不能超過65536,不然編譯會報錯,但是我們在開發App時肯定會集成一堆庫,方法數一般都是超過65536的,解決這個問題的辦法就是:一個dex裝不下,用多個dex來裝,gradle增加一行配置:multiDexEnabled true。
dex文件的應用場景網上介紹的很多,本文不做介紹。而是對項目中實際遇到的問題進行剖析,從而對dex優化有進一步的理解。
ART(Android runtime)是什么,它是虛擬機,運營java代碼、APP用的。參考Android發展史,Android 5.0把ART作為默認的虛擬機,而不是Android4.4及之前使用的DVM(Dalvik VM)了。
回顧一下DVM和ART和Android的關系,我們先來了解運行Java的幾種虛擬機的工作機制:(1)JVM:JVM虛擬機運行的是java字節碼。Java文件到JVM的過程是:java -> java bytecode(class) -> java bytecode(jar)
DVM:DVM虛擬機解析執行的dex字節碼。Java文件到DVM的過程是:java -> java bytecode(class) -> dalvik bytecode(dex)
ART:ART虛擬機執行本地機器碼。Java文件到ART的過程是:java -> java bytecode(class) -> dalvik bytecode(dex) -> optimized android runtime machine code(oat)
可以看到,DVM到ART的演變,實際上是java文件到虛擬機的執行代碼的過渡,相對而言,ART多了oat的過程,ART使用AOT(Ahead-Of-Time)編譯,在應用第一次安裝的時候,字節碼預編譯成機器碼存在本地,DVM是使用JIT(Just-In-Time)編譯,在應用每次運行的時候,字節碼都需要通過編譯器即時轉換為機器碼才能繼續執行。ART相對于DVM,省去了每次解析字節碼的過程,所以運行時占用的內存會減少,提升應用的運行效率。
ART在Android5.0時代,號稱使用AOT即可讓系統運行在512M的機器上。從 Android 7.0(簡稱 N)開始,ART結合 AOT、即時(JIT)編譯和配置文件引導型編譯。
這幾種模式可以組合配置,以谷歌的Pixel 設備舉例,配置了以下編譯流程:
1)最初安裝應用時不進行任何 AOT 編譯。應用前幾次運行時,系統會對其進行解譯,并對經常執行的方法進行 JIT 編譯。
2)當設備閑置和充電時,編譯守護進程會運行,以便根據在應用前幾次運行期間生成的配置文件對常用代碼進行 AOT 編譯。
下一次重新啟動應用時將會使用配置文件引導型代碼,并避免在運行時對已經編譯過的方法進行 JIT 編譯。在應用后續運行期間進行了 JIT 編譯的方法將會被添加到配置文件中,然后編譯守護進程將會對這些方法進行 AOT 編譯。
ART 包括一個編譯器(dex2oat 工具)和一個為啟動 Zygote 而加載的運行時(libart.so)。dex2oat 工具接受一個 APK 文件,并生成一個或多個編譯文件,然后運行時將會加載這些文件。文件的個數、擴展名和名稱會因版本而異,但在 Android O 版本中,將會生成以下文件:
vdex:其中包含 APK 的未壓縮 DEX 代碼,另外還有一些旨在加快驗證速度的元數據。
odex:其中包含 APK 中經過 AOT 編譯的方法代碼。
art (optional):其中包含 APK 中列出的某些字符串和類的 ART 內部表示,用于加快應用啟動速度。
解壓一個APK(以廠商的系統應用包舉例)的包,可以看到下面的結構,不含有任何dex文件
再看下這個應用在手機中的目錄結構,vdex、odex文件包含apk的所有代碼,正常也會包含classes.dex文件。由于vdex、odex是機器碼,沒辦法直接轉成可以查看的二級制碼查看(也可能是我使用的工具不對)。
可能是系統編譯的bug,也可能是生成了ART文件之后,對odex、vdex文件做了二次處理,現象是這樣的,嘗試獲取odex中的dex文件,提示不含有dex文件。
為了再次確認odex里面是否真的含有dex文件,使用010Editor再次確認,可以看到recent Files下面仍然是沒有dex文件的。
嘗試獲取vdex中的dex文件,也是無法獲取的。
所以說,odex(或者vdex)中含有classes.dex的說法是不正確的。
阿里的一個路由組件,功能很多,我這邊的實際使用場景是進行頁面跳轉。具體功能可以參考阿里峰會上對arouter的介紹。
借鑒峰會中提到的一點作為鋪墊,也是我們下面將要講述的一點。“最后想分享的就是ARouter的未來開發計劃。未來ARouter會支持插件化并且支持生成映射關系文檔,因為插件化是現在很多大型APP中會使用的技術方案,很多的Dex和功能是動態地下發到APP中的,而在這種情況下,是無法找到所有的Dex文件的,也就是對于沒有加載過的Dex而言,里面的映射關系是跳轉不過去的,所以一旦Dex文件位置發生變動,常規的方案是無法找到Dex的,也不能實現映射文件初始化,這一部分會在后面的版本中進行支持”。
阿里可以識別的arouter路徑如下:
換句話說,arouter可能因為dex文件的位置變化或者路徑變化,而無法找到。
2.4中提到了odex文件中不含有dex,而arouter查找路徑遵循分組按需加載的規則,歸結到底,實際上就是對class文件的查找,如下圖:
而class文件的信息記錄在dex文件中,所以出現了異常,使用arouter進行頁面跳轉的時候,出現classNotFound exception。
想要找到解決方案,就要知道怎么樣讓odex對arouter路徑不產生影響,這方面,可能在沒有相關經驗的時候,很難找到解決方案,只能一點點查找。通過搜索ART的工作原理,找到文章《配置ART》,其中文章提到:
也就是說通過配置LOCAL_DEX_PREOPT的屬性,可以防止odex優化,于是找到Android.mk中設置該屬性的地方進行設置LOCAL_DEX_PREOPT := nostripping。
既在編譯的時候做dex優化(生成odex文件),又不從apk里剝離dex。于是有了下面的apk生成之后的路徑對比,再看下dex不被剝離的路徑,下面含有了classes.dex文件。
使用jadx打開這個classes.dex文件,發現arouter的路徑文件就在這里,所以arouter的跳轉正常了,異常不再出現。
odex優化這種系統做的事情,往往會出現一些意想不到的結果,如果你負責廠商的應用,經常需要內置項目,這時候要注意了,當你的應用中含有第三方框架的時候,要注意路徑、資源的引用都是沒問題的,雖然正常情況下,odex文件不會對你的路徑產生干擾,但是也難免odex出現失誤,因為對于odex來說,里面的資源無需保存,生成art文件能夠運行即可。合理使用art的配置,可以幫助解決很多問題。
“dex優化對Arouter查找路徑有什么影響”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。