成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

支付寶Android包大小極致壓縮

移動開發(fā) Android
本章節(jié)我們將圍繞《支付寶 App 構(gòu)建優(yōu)化解析》另啟新系列,細分拆解客戶端在“代碼管理”、“證書管理”、“版本管理”、“構(gòu)建打包”等維度的具體實現(xiàn)方案展開討論,帶領(lǐng)大家進一步了解支付寶在 App 構(gòu)建模塊下的持續(xù)優(yōu)化。

前言

本章節(jié)我們將圍繞《支付寶 App 構(gòu)建優(yōu)化解析》另啟新系列,細分拆解客戶端在“代碼管理”、“證書管理”、“版本管理”、“構(gòu)建打包”等維度的具體實現(xiàn)方案展開討論,帶領(lǐng)大家進一步了解支付寶在 App 構(gòu)建模塊下的持續(xù)優(yōu)化。

本節(jié)將主要記錄通過對支付寶 Android 包大小進行壓縮,來改善運行效率和質(zhì)量。

背景

包大小的重要性已經(jīng)不需要多說,包大小直接影響用戶的下載,留存,還有部分廠商預(yù)裝強制要求必須小于一定的值。但是隨著業(yè)務(wù)的迭代開發(fā),應(yīng)用會越來越大,安裝包會不停的膨脹,所以包大小縮減是一個長期的治理過程。

方案

支付寶也一直在優(yōu)化包大小的方向上努力,我們引入了很多方案。

  • 比如:proguard 代碼混淆,圖片從 png 到 tinypng 到 webp,引入 7zip 壓縮方案等。

本方案是有別于上面這些常規(guī)的方案,是通過直接刪 dex 中的無用信息,達到支付寶包大小瞬間減小 2.1M 的目的,并且不影響整個的運行邏輯和性能,甚至還能降低一點運行內(nèi)存。

方案介紹

引言

在講詳細方案前得稍微說說整個 Java 系的調(diào)試邏輯。

JVM 運行時加載的是 .class 文件,Android 為了使包大小更緊湊,并且運行更高效發(fā)明了 dalvik 和 art 虛擬機,兩種虛擬機運行的都是 .dex 文件(當然 art 虛擬機還可以同時運行 oat 文件,不在本文章討論范圍)。

所以 dex 文件里面信息的內(nèi)容和 class 文件包含的信息是完全一致的,不同的是 dex 文件對 class 中的信息做了去重,一個 dex 包含了很多的 class 文件,并且在結(jié)構(gòu)上有比較大的差異,class 是流式的結(jié)構(gòu),dex 是分區(qū)結(jié)構(gòu),各個區(qū)塊間通過 offset 索引。后面就只提 dex 的結(jié)構(gòu),不再提 class 的結(jié)構(gòu)。dex 的結(jié)構(gòu)可以用下面這張圖表示:

支付寶Android包大小極致壓縮

dex 文件的結(jié)構(gòu)其實非常清晰,分幾個大塊,header 區(qū),索引區(qū),data 區(qū),map 區(qū)。本優(yōu)化方案優(yōu)化刪除的就是 data 區(qū)中的 debugItems 區(qū)域。

debugItem 干嗎用?

首先得知道 debugItem 里面存了什么?

里面主要包含兩種信息:

  • 函數(shù)的參數(shù)變量和所有的局部變量
  • 所有的指令集行號和源文件行號的對應(yīng)關(guān)系

有什么用呢:

  • 第一點其實很明顯,既然叫 debugItem,那么肯定就是 debug 的時候用的嘍,我們平時在用 IDE 進行斷點和單步調(diào)試的時候都會用到這個區(qū)域。
  • 第二點作用那就是上報 crash 或者主動獲取調(diào)用堆棧的時候用的,因為虛擬機真正執(zhí)行的時候是執(zhí)行的指令集,上報堆棧會上報 crash 的對應(yīng)源文件行號,此時正是通過這個 debugItem 來獲取對應(yīng)的行號,可以用下面的截圖比較直觀的了解:

支付寶Android包大小極致壓縮

上圖是一個比較常見的 crash 信息,紅框中的行號便是通過查找這個 debugItem 來獲取的。

debugItem 有多大?

在支付寶的場景下,debug 包有 4-5M,release 包有 3.5M 左右,占 dex 文件大小的比例在 5.5% 左右,和 google 官方的數(shù)據(jù)是一致的。如果能把這部分直接去掉,是不是很誘人!

debugItem 能直接去掉嗎?

顯然不能,如果去掉了,那所有上報的 crash 信息就會沒有行號,所有的行號都會變成 -1,會被噴的找不到北。

其實在 proguard 的時候就是有配置可以去掉或保留這個行號信息,-keep SourceFile, LineNumberTable 就是這個作用,為了方便定位問題,基本所有的開發(fā)都保留了這個配置。

所以,方案的核心思路就是去掉 debugItem,同時又能讓 crash 上報的時候能拿到正確的行號。至于 IDE 調(diào)試,這個比較好解決,我們只要處理 release 包就行了,debug 包不處理。

方案一

核心思路也比較簡單,就是行號查找離線化,讓本來存放在 App 中的行號對應(yīng)關(guān)系提前抽離出來存放在服務(wù)端,crash 上報的時候通過提前抽離的行號表進行行號反解,解決 crash 信息上報無行號,無法定位的問題。

思路雖然簡單,實現(xiàn)的時候還是有點復(fù)雜,推動上線也比較曲折,方案經(jīng)過幾次調(diào)整,大概的方案可以用下面一張圖來抽象:

支付寶Android包大小極致壓縮

如上圖,核心點有四個:

  • 修改 proguard,利用 proguard 來刪除 debugItem (去掉 -keep lineNumberTable),在刪除行號表之前 dump 出一個臨時的 dex。
  • 修改 dexdump,把臨時的 dex 中的行號表關(guān)系 dump 成一個 dexpcmapping 文件(指令集行號和源文件行號映射關(guān)系),并存至服務(wù)端。
  • hook app runtime 的 crash handler,把 crash 時的指令集行號上報到反解平臺。
  • 反解平臺通過上報指令集行號和提前準備好 dexpcmapping 文件反解出正確的行號。

上面這套方案大概花了兩個多星期,擼出了整個 demo,其它幾個改造點都不是很難,難點還是在指令集行號的上報。

我們知道所有的 crash 最終都是會有一個 throwable 對象,里面保存了整個堆棧信息,經(jīng)過反復(fù)的閱讀源碼和嘗試,發(fā)現(xiàn)我要的指令集行號其實也在這個對象里面。可以用下面一幅簡單的圖示意:

支付寶Android包大小極致壓縮

在打印 crash 堆棧信息前,每個 throwable 都會調(diào)用art虛擬機提供的一個 jni 方法,返回一個內(nèi)部的對象叫 stackTrace 保存在 Throwable 對象中,這個 stackTrace 對象里面保存的便是整個方法的調(diào)用棧,當然也包括指令集行號,后續(xù)獲取實際的堆棧信息時會再調(diào)用一個 art 的 jni 方法,把這個 stackTrace 方法丟過去,底層通過這個 stackTrace 對象中的指令集行號反解出正式的源文件行號。

好了,其實很簡單,反射獲取下這個 Throwable 中的 stackTrace 對象,拿到指令集行號,然后,上報。

這里要注意的一個點,比較惡心,每個虛擬機的實現(xiàn)都不一樣,首先內(nèi)部對象的名字,有些叫 stackTrace,有些叫 backstrace,然后這個內(nèi)部對象的類型也非常有,有些是 int 數(shù)組,有些是 long 數(shù)組,有些是對象數(shù)組,但是都會有這個指令集行號,需要針對不同的虛擬機版本使用不同的方法去解析這個對象,大概要兼容4種虛擬機,4.x, 5.x, 6.x, 7.x,7.x 虛擬機之后的就統(tǒng)一了。

方案二

上面這套方案其實挺完美的,沒有什么兼容性問題,刪除是直接利用 proguard,獲取指令集行號直接在 java 層獲取,不需要各種 hook,如果只需要處理 crash 的上報,方案一足夠了,但是在支付寶有很多場景是遠遠不夠的。

比如:

  • 性能,CPU,內(nèi)存異常時調(diào)用棧。
  • native crash 時的 Java 調(diào)用棧。

上面這些 case 都會涉及到堆棧信息,方案一中通過反射調(diào)用 throwable 中的 stackTrace 內(nèi)部對象根本搞不定,需要換種方法。

最開始的思路是嘗試 hook art 虛擬機,每天翻源碼,看看可以 hook 的點,最后還是放棄了,一個是擔(dān)心兼容性問題,另一個是 hook 的點太多,比較慌。

最后換了一種思路,嘗試直接修改 dex 文件,保留一小塊 debugItem,讓系統(tǒng)查找行號的時候指令集行號和源文件行號保持一致,這樣就什么都不用做,任何監(jiān)控上報的行號都直接變成了指令集行號,只需修改 dex 文件。可以用下面的示意圖表示:

支付寶Android包大小極致壓縮

如上圖:本來每一個方法都會有一個 debugInfoItem,每一個 debuginfoItem 里面都有一個指令集行號和源文件行號的映射關(guān)系,我做的修改其實非常簡單,就是把多余的 debugInfoItem 全部刪掉了,只留了一個 debugInfoItem,所有的方法都指向同一個 debugInfoItem,并且這個 debugInfoItem 中的指令集行號和源文件行號保持一致,這樣不管用什么方式來查行號,拿到的都是指令集行號。

其中也踩過很多坑,其實光留一個 debugInfoItem 是不夠的,要兼容所有虛擬機的查找方式,需要對 debugInfoItem 進行分區(qū),并且 debugInfoItem 表不能太大,遇到過一個坑就是 androidO 上進行 dex2oat 優(yōu)化的時候,會頻繁的遍歷這個 debugInfoItem,導(dǎo)致 AOT 編譯比較慢,最后都通過 debugInfoItem 分區(qū)解決了。

這個方案比較徹底,不用改 proguard,也不用 hook native。不過如果只需要處理 crash 的行號問題,那還是首推方案一,這個方案改動有點大,前期也是每天研究 dex 的文件結(jié)構(gòu),摳每一個細節(jié),有比較大的把握時才敢改。

小結(jié)

目前該方案已經(jīng)在支付寶正式上線,前面經(jīng)過好幾輪的外灰驗證,還是比較穩(wěn)定的。支付寶整體包大小減少了 2.1M 左右,真實的 dex 大小減少 3.5M 左右。

通過本節(jié)內(nèi)容,我們初步了解了支付寶在 Android 客戶端如何通過包大小壓縮以提升 App 運行效率和質(zhì)量。關(guān)于 Android 端包大小壓縮的設(shè)計思路和具體實踐,同樣期待你們的反饋,歡迎一起探討交流。

責(zé)任編輯:未麗燕 來源: 安卓巴士Android開發(fā)者門戶
相關(guān)推薦

2021-01-25 14:13:26

iOS支付寶支付

2021-09-09 15:30:28

鴻蒙HarmonyOS應(yīng)用

2014-11-17 10:52:56

支付寶去阿里化

2009-09-17 12:15:28

互聯(lián)網(wǎng)

2018-03-27 12:02:31

央行支付寶紅包

2011-04-21 11:27:42

Firefox支付寶

2017-12-18 18:23:09

支付寶掃碼賺錢支付寶套路

2013-10-31 11:24:53

支付寶漏洞支付寶漏洞

2009-11-23 10:02:22

PHP支付寶接口

2009-12-14 16:31:00

Linux安裝支付寶

2013-10-11 09:41:01

Windows 8.1支付寶

2009-08-26 16:07:09

支付寶網(wǎng)上購物安全邁克菲

2023-11-28 08:53:15

2020-08-14 11:00:41

支付寶

2021-03-30 09:59:52

支付寶加密數(shù)據(jù)泄露

2015-05-28 09:52:21

光纖支付寶

2021-05-12 07:10:55

支付寶數(shù)字人民幣移動應(yīng)用

2013-06-20 10:45:10

余額寶支付寶大數(shù)據(jù)

2025-02-18 16:00:00

SpringBoot支付Java

2025-02-17 00:00:45

接口支付寶沙箱
點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 久久精品综合 | av在线一区二区 | 亚洲国产精品久久久久秋霞不卡 | av一区在线观看 | 日韩中文字幕视频在线 | 九一在线 | 国产欧美精品 | 成人精品在线视频 | 一区二区三区精品在线视频 | 精品一区国产 | 亚洲不卡在线观看 | 久久夜视频 | 三a毛片| 性一交一乱一伦视频免费观看 | 亚洲精品2区 | 成年网站在线观看 | 午夜影院黄 | 亚洲精品视频免费观看 | 国产精品久久久久久久久久软件 | 欧美高清视频一区 | 九九在线| 毛片免费看 | 久久99精品视频 | av电影手机在线看 | 99久久久国产精品免费消防器 | 日韩精品一区二区三区中文字幕 | 日日av| 国产xxxx搡xxxxx搡麻豆 | 中文字幕在线精品 | 热久久999| 亚洲精品在线免费 | 成人免费视频在线观看 | 国产视频久久久久 | 网站黄色av | 色天堂影院 | 99热这里只有精品8 激情毛片 | 亚洲精品视频免费看 | 国产精品美女久久久久aⅴ国产馆 | 亚洲国产免费 | 日本综合在线观看 | 久久久久久久久久久久亚洲 |