應用性能優化之 VerifyClass

爲了加速應用冷啓動過程且不過度涉及業務改動,本文從虛擬機加載類的過程中找到優化項,且與業界的方案作了對比,並實現了半自動化的分析功能。類在使用或實例化之前需要被加載到虛擬機中並進行初始化。整個過程如下圖所示:主要由 LoadingClass 和 InitializingClass 兩部分組合。

LoadingClass 旨在把 Class 從 Dex 加載到虛擬機中,但不涉及類的使用或執行流程。InitializingClass 旨在保證使用類前已經經過了初始化流程,此流程嵌入類的使用或執行過程中。

加載類

DefineClass 主要通過 SetupClass、InsertClass 以及 LoadClass 將一個類加載到虛擬機中,最後返回 mirror:Class 對象指針。

類初始化

類的屬性或方法在使用前必須經過類的初始化。

覈驗類

VerifyClass 使用 VerifyClassUsingOatFile 或 PerformClassVerification 方法之一去核查 Class。其中 PerformClassVerification 就包含了 Systrace 中耗時 VerifyClass 的 Tag,如下圖所示:

提前發現

從上面的分析可以看出,應該儘可能讓覈查走 VerifyClassUsingOatFile 流程,即通過 Oat 文件狀態位覈查成功。Oat 文件中類的狀態位是什麼以及爲什麼狀態位不等於 kStatusVerified 是問題的突破點。

通過 oatdump 命令去 dump 相應的 odex 文件,可以查看類的狀態位,操作方式如下:

VLOG 默認是不會被打印的,需要動態開啓,開啓的方式可以通過:art::gLogVerbosity.class_linker = true 而打開,因爲本項目需要看到 dex2oat 和其他進程的打印情況,本人是在系統源碼中進行編譯生成的 so,然後,通過 ptrace 注入 so 到 Zygote 的,此方法需要 root 設備,如果只需要查看本進程,應不需要這麼麻煩,具體方法還未探索,但思路應該是一致的。舉例如下,本人碰到的問題是 AppCompat 包中的類不能被覈驗通過。

解決方案

將 Runtime 對象中的 verify_設置成 verifier::VerifyMode::kNone。

如果是應用需要兼容多個不同版本的 ROM,也可以按照 ROM 版本的不同,使用 App Bundle 下發 “最合適” 的 App。

平臺化

圖片過大,截圖處理

爲了降低方案實施難度,現已將方案平臺化,只要將 apk 拖入網頁中即可看到類覈驗不通過的原因。

轉自:掘金  大力智能技術

https://juejin.cn/post/6951225539990388750

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/rHMC8AmzkxhkY10B3bzPWA