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

高效開發之編譯插樁

移動開發 移動應用
在這次的和家親APP性能優化尤其是啟動至首屏專項優化中,使用了Gradle+ASM編譯插樁技術實現apk全局耗時方法統計,本文以此為例讓你認識“插樁”這個效率利器。
作者|劉素云,單位:智慧家庭運營中心

?Labs 導讀

插樁技術非常有趣也很有價值,學會這項技術以后,我們就可以隨心所欲地操控代碼,滿足不同場景的需求。很多框架都離不開這個技術,如常見的ButterKnife 注解框架,數據庫 ORM 框架、APM性能監控、埋點統計等。

和家親是一款智慧家庭綜合服務入口APP。客戶端的性能直接影響用戶體驗,在這次的和家親APP性能優化尤其是啟動至首屏專項優化中,使用了Gradle+ASM編譯插樁技術實現apk全局耗時方法統計,本文以此為例讓你認識“插樁”這個效率利器。

Part 01  編譯插樁

顧名思義,所謂的編譯插樁就是在代碼編譯期間修改已有的代碼或者生成新代碼。

在學習插樁之前,你首先需要了解相關基礎技術,包括Android打包大致流程、class字節碼文件結構、gradle Transform task及ASM字節碼操作框架等。后面會做簡單介紹,若要詳細了解,你可以仔細閱讀參考文獻。

下圖為android編譯插樁示意圖。

圖片

字節碼(Bytecode):“.class”文件的是 Java 字節碼、“.dex”文件的是 Dalvik 字節碼。我們這里的ASM插樁方法是操作Java 字節碼。

使用場景:對于代碼監控、代碼修改以及代碼分析這三個場景,一般采用操作字節碼的方式,如無埋點統計上報、輕量級AOP等。應用到在Android中,可以用來做用行為統計、方法耗時統計等功能。

Part 02  ASM字節碼框架

ASM是一個java字節碼操縱框架,它能被用來動態生成類或者增強既有類的功能。

2.1 class文件

了解ASM框架使用之前,必須先了解下class文件格式,一個完整的 class字節碼文件包括:

  • 魔數與class文件版本
  • 常量池
  • 訪問標志
  • 類索引、父類索引、接口索引
  • 字段表集合
  • 方法表集合
  • 屬性表集合

為方便查看字節碼文件,kotlin代碼android studio 有自帶工具tools--show kotlin bytecode,java代碼可以安裝jclasslib查看。

2.2 ASM框架使用

ASM的架構主要是采用了訪問者模式來設計,所謂訪問者模式就是封裝一些作用于某種數據結構中的各元素的操作,它可以在不改變數據結構的前提下定義作用于這些元素的新的操作。具體在ASM框架中應用就是將.class類文件的內容從頭到尾掃描一遍,每次掃描到類文件相應的內容時,都會調用ClassVisitor內部相應的方法。該方法會返回一個對應的字節碼操作對象(比如,visitMethod()返回MethodVisitor實例),通過修改這個對象,就可以修改class文件相應結構部分內容,最后將這個ClassVisitor字節碼內容覆蓋原來.class文件就實現了類文件的代碼切入。

圖片

2.3 ASM工具

工欲善其事,必先利其器。在使用 ASM 插入字節碼時,如果你不熟悉字節碼相關語法和規則可能對于插入字節碼代碼束手無策了。幸好 ASM官方開發了一款IDE插件,可以將Java代碼 轉換成 ASM 字節碼類型代碼,這樣再使用ASM插入字節碼時就比較方便了。利用插件ASM bytecode outline輕松查看字節碼及對應ASM框架代碼。

圖片

Part 03  Gradle Transform

Gradle Transform 是 Android 官方提供的在apk編譯打包的流程中將 .class 文件到 .dex 轉換這一階段用來修改 .class 文件的一套標準 API。這一應用現在主要集中在字節碼查找、代碼注入等。

3.1 Transform原理

Transform是android gradle api中的一部分,它可以在android項目的.class文件編譯為.dex文件之前,得到所有的.class文件,在Transform中處理。使用Transform API, 我們完全可以不用去關注相關task的生成與執行流程, 它讓我們可以只聚焦在如何對輸入的類文件進行處理。

圖片

每個Transform其實都是一個gradle task,Android編譯器中的TaskManager將每個Transform串連起來,第一個Transform接收來自javac編譯的結果,以及已經拉取到在本地的第三方依賴(jar、aar),還有resource資源。這些編譯的中間產物,在Transform組成的鏈條上流動,每個Transform節點可以對class進行處理再傳遞給下一個Transform。我們常見的混淆,Desugar等邏輯,它們的實現如今都是封裝在一個個Transform中,而我們自定義的Transform,會插入到這個Transform鏈條的最前面。

自定義的transform在build控制臺可以看到對應的task,輸出內容可以在build\intermediates\transforms\對應目錄找到。

3.2 Transform自定義實現

想要自定義transform,必須實現以下幾個方法:

  • getName():返回transform名稱標識
  • getInputTypes(): 輸入類型包括倆種,CLASSES 和 RESOURCES分別代表java的class文件和資源文件
  • getScopes(): 定義Transform需要處理那些輸入文件
  • isIncremental(): 表示是否支持增量編譯,支持增量編譯,可以節省一些編譯的時間和資源,一個好的transform都應該支持增量編譯
  • Transform(): 主要方法,入參TransformInvocation是一個接口,提供一些關于輸入的基本信息,利用這些接口就可以獲得編譯流程中的class文件進行操作

在apk打包過程中,除了自定義的Transform,還有系統提供原生的一些Transform,每個 Transform 在處理完之后交給下一個 Transform,是一個鏈式結構。下圖為自定義Transform實現apk打包流程中字節碼插樁的流程示意圖,簡單來說就是以下幾步:

  1. 篩選符合條件的 Class 文件,其中 Class 有兩種可能的文件來源:jar包和特定目錄;
  2. 利用ASM框架讀取 Class 文件包含的類信息(例如接口、注解等)進一步篩選符合條件的 Class 文件;
  3. 對最終符合條件的 Class 做處理(修改字節碼、插樁等);
  4. 將產物拷貝至 Transform 的輸出目錄,作為下一個 Transform 的輸入;

圖片

Part 04  實戰:APK函數耗時插樁

和家親是智慧家庭綜合服務入口APP,隨著用戶量的激增,客戶端的性能問題愈加明顯,啟動性能作為APP使用體驗的門面,啟動耗時較長很可能削減用戶使用APP的興趣。在這次的啟動至首屏專項優化中,需要查找啟動過程耗時方法并優化,由于業務復雜及SDK接入眾多,雖然也有原生工具profile,但是用過的都知道存在不易捕獲尤其是啟動階段,且無法輸出調用堆棧等問題。需要實現一個快速排查高耗時方法的工具,此次優化通過Gradle TransForm+ASM方式實現了編譯插樁全局耗時方法統計,輔助啟動優化分析,最終啟動到首屏展示耗時從4.5s將至3.2s,啟動提速30%,效果顯著。

4.1 實現思路

在性能優化階段,需要函數耗時統計以解決啟動慢、卡頓等問題。對Android打包過程和自定義Gradle插件了解后發現,java文件會先轉化為class文件,然后再轉化為dex文件。而通過Gradle插件提供的Transform API,可以在編譯成dex文件之前得到class文件。得到class文件之后,便可以通過ASM對字節碼進行修改,即可完成字節碼插樁,插入時間統計打印代碼,大于閾值則輸出調用堆棧。主要實現以下功能:

  • 自定義Gradle插件
  • 處理class,在方法出口及入口插入耗時統計
  • 文件替換

圖片

創建一個buildsrc模塊

在 Android 工程中,buildSrc 是 gradle默認的插件目錄,編譯 gradle的時候會自動識別這個目錄,因此在 buildSrc 下編寫的插件,我們可以直接進行引用。通常我們會使用這種方式進行插件的調試。創建buildSrc 目錄,配置plugin插件相關配置及依賴(新版本Gradle plugin已經支持kotlin語言編寫)。

注冊Transform

想要使用gradle-transform-api,我們必須要先實現一個gradle插件,然后在插件中注冊一個Transform,同時需要在gradle-plugins目錄的.properties文件聲明插件實現者如:

implementation-class=com.xxx.xxx.SystemTracePluginTest

圖片

獲取所有class文件

transform()通過參數inputs獲取所有class文件,包括源碼編譯后的class文件及三方的jar包。

圖片

字節碼修改及文件寫回

經過上面的步驟,我們已經到輸入文件,也確定了輸出路徑,現在我們只要來處理這些文件,然后輸出到輸出路徑就可以了。這里需要注意的是,就算你不想修改某個class文件,你也應該將它原樣拷貝過去,否則這個文件就丟失了。

圖片

利用ASM框架,在遍歷到方法出口及入口即onMethodEnter、onMethodExit回調中插入耗時統計字節碼,相應的字節碼可以用上面的工具jclaslib或者asm codeoutline查看得到。(以下代碼只是部分示例,細節完善如之針對部分包名統計、getset方法排除等未在次列出)

圖片

應用插件完成插樁

app工程apply plugin ‘pluginname’ ,Gradle task會有對應task name 輸出則Transform task執行,運行apk,可以看到插入的自定義耗時統計方法輸出,比如小編在耗時統計方法加入了邏輯,耗時超過自定義閾值logcat打印日志及堆棧信息。

圖片

通過插樁的形式,使用apk的時候可以非常清晰的統計出耗時方法,還有調用堆棧,方便后續性能優化。能夠彌補傳統的profile工具性能分析的一些不足,比如只能捕獲短時間,需要自己尋找長耗時方法等問題。

Part 05  結語 

編譯插樁這個技術應用場景越來越多,涉及的知識較多,但是相信在你熟悉Android打包流程、class字節碼文件結構、Gradle Transform API、ASM之后,相信你會覺得插樁so easy,android開發高手課之編譯插樁又get了一個新技能!在性能優化過程中,已經不止一次用到編譯插樁的技術了,除了方法耗時統計,我們還使用插樁加hook代理的方式做大圖監控,網絡監控、線程優化等工作,例如網絡數據監控 的實現,就是在 網絡層通過 hook 網絡庫方法和自動化注入攔截器的形式,實現網絡請求的全過程監控,包括獲取握手時長,首包時間,DNS 耗時,網絡耗時等各個網絡階段的信息。大圖監控則是通過hook各大圖片加載庫如Glide、picasso在圖片加載過程增加監聽計算圖片大小,針對大圖過濾輸出等。讓我們一起學習“插樁”這個效率利器吧。

參考文獻

[1]https://rebooters.github.io/2020/01/04/Gradle-Transform-ASM-%E6%8E%A2%E7%B4%A2/

[2]https://cloud.tencent.com/developer/article/1399805

[3]https://time.geekbang.org/column/intro/142?tab=catalog?

責任編輯:未麗燕 來源: 移動Labs
相關推薦

2021-02-05 07:58:03

字節碼插樁交付

2011-08-30 16:55:31

MTK開發編譯

2020-09-08 06:28:42

大數據應用

2011-06-13 14:49:57

Qt Designer

2022-05-13 09:40:51

代碼可行應用性能

2022-01-10 07:57:25

Linux 插樁Linux 系統

2010-03-03 15:06:52

Android 游戲開

2016-11-23 08:10:16

Android St JRebel調試神器

2023-03-29 07:36:32

鏈表頭插尾插

2025-05-12 07:07:53

SpringBoot映射URL

2013-02-26 11:00:35

用友UAP敏捷開發跨平臺

2024-04-01 08:26:30

單測覆蓋率字節碼

2017-03-27 18:05:49

Linux內核編譯與開發

2017-06-09 09:21:44

2023-06-20 15:58:22

VMwareSpring

2009-06-11 14:11:33

代碼混淆Java反編譯

2022-01-21 19:00:44

前端JS框架

2015-09-06 14:50:05

安卓app高效開發

2020-11-26 08:38:57

前端 js 庫vue

2013-05-02 13:02:59

開發環境自動化團隊
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 欧美色综合天天久久综合精品 | 伊人网综合在线观看 | 欧美在线| 国产91在线观看 | 亚洲成人综合在线 | 国产欧美一区二区三区国产幕精品 | 久草资源在线 | 欧美激情综合色综合啪啪五月 | 亚洲综合首页 | 日本成人中文字幕在线观看 | 久久成人免费 | 日韩av电影院 | 日韩欧美在 | 在线一区二区三区 | www.99热.com | 自拍视频网站 | 亚洲va国产日韩欧美精品色婷婷 | 欧美一区二区在线看 | 一级毛片在线播放 | 999热在线视频 | 亚洲天堂中文字幕 | yiren22 亚洲综合| 天天激情综合 | 波多野结衣在线观看一区二区三区 | 国产一区二区精品在线观看 | 亚洲欧美中文日韩在线 | 在线āv视频 | 欧美激情一区二区 | 国产一区二区三区精品久久久 | 一区欧美| 成人在线视频免费观看 | 日韩中文字幕视频在线观看 | 国产午夜精品一区二区三区四区 | 日韩国产精品一区二区三区 | 日韩av在线不卡 | 91av在线免费看| 免费一区在线观看 | 精品国产欧美一区二区三区成人 | 国产成人精品一区二区三区四区 | 在线黄| 狠狠操狠狠搞 |