字節(jié)碼插樁實戰(zhàn) javassit + gradle transform + annotation 統(tǒng)計方法耗時

前言:上一篇我們簡單介紹了下字節(jié)碼插樁過程,這里主要介紹如何通過一行注解來實現(xiàn)統(tǒng)計方法耗時。
在做app啟動耗時優(yōu)化的時候迁霎,我們是有這個需求的,雖然可以通過profile來查看唯卖。

javassit

介紹:Javassist是一個動態(tài)類庫眠寿,可以用來檢查、”動態(tài)”修改以及創(chuàng)建 Java類山憨。其功能與jdk自帶的反射功能類似查乒,但比反射功能更強(qiáng)大。

常用類:

  • ClassPool:javassist的類池郁竟,使用ClassPool類可以跟蹤和控制所操作的類,它的工作方式與 JVM類裝載器非常相似玛迄,

  • CtClass: CtClass提供了檢查類數(shù)據(jù)(如字段和方法)以及在類中添加新字段、方法和構(gòu)造函數(shù)棚亩、以及改變類蓖议、父類和接口的方法虏杰。不過Javassist 并未提供刪除類中字段、方法或者構(gòu)造函數(shù)的任何方法勒虾。

  • CtField:用來訪問域

  • CtMethod :用來訪問方法

  • CtConstructor:用來訪問構(gòu)造器

gradle transform

transform.png

getName:用于指明本Transform的名字纺阔,這個 name 并不是最終的名字,在TransformManager 中會對名字再處理

getInputTypes:用于指明Transform的輸入類型修然,可以作為輸入過濾的手段

–CLASSES表示要處理編譯后的字節(jié)碼州弟,可能是 jar 包也可能是目錄

 –RESOURCES表示處理標(biāo)準(zhǔn)的 java 資源

getScopes:用于指明Transform的作用域

–PROJECT                         只處理當(dāng)前項目

–SUB_PROJECTS  只處理子項目

–PROJECT_LOCAL_DEPS  只處理當(dāng)前項目的本地依賴,例如jar, aar

–EXTERNAL_LIBRARIES  只處理外部的依賴庫

–PROVIDED_ONLY  只處理本地或遠(yuǎn)程以provided形式引入的依賴庫

–TESTED_CODE                         只處理測試代碼

isIncremental:用于指明是否是增量構(gòu)建。

transform:核心方法低零,用于自定義處理,在這個方法中我們可以拿到要處理的.class文件路徑婆翔、jar包路徑、輸出文件路徑等掏婶,拿到文件之后就可以對他們進(jìn)行操作

inputs.each { TransformInput input ->
            input.directoryInputs.each { DirectoryInput directoryInput ->
                if (directoryInput.file.isDirectory()) {
                    println "==== directoryInput.file = " + directoryInput.file
                    directoryInput.file.eachFileRecurse { File file ->
                        // ...對目錄進(jìn)行插入字節(jié)碼
                    }
                }
                //處理完輸入文件之后啃奴,要把輸出給下一個任務(wù)
                def dest = outputProvider.getContentLocation(directoryInput.name, directoryInput.contentTypes, directoryInput.scopes, Format.DIRECTORY)
                FileUtils.copyDirectory(directoryInput.file, dest)
            }

input.jarInputs.each { JarInput jarInput ->
                println "------=== jarInput.file === " + jarInput.file.getAbsolutePath()
                File tempFile = null
                if (jarInput.file.getAbsolutePath().endsWith(".jar")) {
                    // ...對jar進(jìn)行插入字節(jié)碼
                }
                /**
                 * 重名輸出文件,因為可能同名,會覆蓋
                 */
                def jarName = jarInput.name
                def md5Name = DigestUtils.md5Hex(jarInput.file.getAbsolutePath())
                if (jarName.endsWith(".jar")) {
                    jarName = jarName.substring(0, jarName.length() - 4)
                }
                //處理jar進(jìn)行字節(jié)碼注入處理
                def dest = outputProvider.getContentLocation(jarName + md5Name, jarInput.contentTypes, jarInput.scopes, Format.JAR)
                FileUtils.copyFile(jarInput.file, dest)
            }
        }

實現(xiàn)步驟

1. 注解類
annatation.png
2. gradle插件去注冊transform

gradle插件的使用請移步 gradle插件

plugin.png
3. transform 操作文件的實現(xiàn)步驟
transformImpl.png
4. 拿到文件后使用javassit操作
ssit1.png
ssit2.png
ssit3.png
5. 將gradle插件 和 注解lib 上傳maven 供app依賴引用

gradle插件上傳maven
Android lib 上傳maven

depend.png
test.png
6. 重新rebuild一下

compileresult.png

可見class文件中test方法已經(jīng)被插入了我們想要的代碼

7. run下看看結(jié)果
clickcosttime.png

后記

這里只是提供了一種啟動優(yōu)化做耗時檢測的場景,還有可以根據(jù)注解去做無痕埋點雄妥,用戶的一些主流程操作鏈路分析等等最蕾。

代碼地址

源碼

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市老厌,隨后出現(xiàn)的幾起案子瘟则,更是在濱河造成了極大的恐慌,老刑警劉巖枝秤,帶你破解...
    沈念sama閱讀 211,948評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件醋拧,死亡現(xiàn)場離奇詭異,居然都是意外死亡淀弹,警方通過查閱死者的電腦和手機(jī)丹壕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,371評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來薇溃,“玉大人菌赖,你說我怎么就攤上這事°逍颍” “怎么了琉用?”我有些...
    開封第一講書人閱讀 157,490評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長策幼。 經(jīng)常有香客問我邑时,道長,這世上最難降的妖魔是什么垄惧? 我笑而不...
    開封第一講書人閱讀 56,521評論 1 284
  • 正文 為了忘掉前任刁愿,我火速辦了婚禮,結(jié)果婚禮上到逊,老公的妹妹穿的比我還像新娘铣口。我一直安慰自己滤钱,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,627評論 6 386
  • 文/花漫 我一把揭開白布脑题。 她就那樣靜靜地躺著件缸,像睡著了一般。 火紅的嫁衣襯著肌膚如雪叔遂。 梳的紋絲不亂的頭發(fā)上他炊,一...
    開封第一講書人閱讀 49,842評論 1 290
  • 那天,我揣著相機(jī)與錄音已艰,去河邊找鬼痊末。 笑死,一個胖子當(dāng)著我的面吹牛哩掺,可吹牛的內(nèi)容都是我干的凿叠。 我是一名探鬼主播,決...
    沈念sama閱讀 38,997評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼嚼吞,長吁一口氣:“原來是場噩夢啊……” “哼盒件!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起舱禽,我...
    開封第一講書人閱讀 37,741評論 0 268
  • 序言:老撾萬榮一對情侶失蹤炒刁,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后誊稚,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體翔始,經(jīng)...
    沈念sama閱讀 44,203評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,534評論 2 327
  • 正文 我和宋清朗相戀三年片吊,在試婚紗的時候發(fā)現(xiàn)自己被綠了绽昏。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,673評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡俏脊,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出肤晓,到底是詐尸還是另有隱情爷贫,我是刑警寧澤,帶...
    沈念sama閱讀 34,339評論 4 330
  • 正文 年R本政府宣布补憾,位于F島的核電站漫萄,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏盈匾。R本人自食惡果不足惜腾务,卻給世界環(huán)境...
    茶點故事閱讀 39,955評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望削饵。 院中可真熱鬧岩瘦,春花似錦未巫、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,770評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至密末,卻和暖如春握爷,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背严里。 一陣腳步聲響...
    開封第一講書人閱讀 32,000評論 1 266
  • 我被黑心中介騙來泰國打工新啼, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人刹碾。 一個月前我還...
    沈念sama閱讀 46,394評論 2 360
  • 正文 我出身青樓师抄,卻偏偏與公主長得像,于是被迫代替她去往敵國和親教硫。 傳聞我的和親對象是個殘疾皇子叨吮,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,562評論 2 349

推薦閱讀更多精彩內(nèi)容

  • 一、gradle Transform 接收一個輸入input,同時需要有一組輸出,作為下一個Transform的輸...
    feifei_fly閱讀 2,787評論 0 0
  • 篇頭語 應(yīng)師傅指導(dǎo)瞬矩,最近研究了一下從Gradle編譯入手茶鉴,實現(xiàn)字節(jié)碼插樁,進(jìn)而實現(xiàn)一些功能景用,其實網(wǎng)上相關(guān)文章也不算...
    小熊兜里有糖閱讀 3,350評論 5 18
  • (轉(zhuǎn)載) 1. 字節(jié)碼 1.1 什么是字節(jié)碼涵叮? Java之所以可以“一次編譯,到處運行”伞插,一是因為JVM針對各種操...
    花神子閱讀 1,376評論 0 5
  • 表情是什么割粮,我認(rèn)為表情就是表現(xiàn)出來的情緒。表情可以傳達(dá)很多信息媚污。高興了當(dāng)然就笑了舀瓢,難過就哭了。兩者是相互影響密不可...
    Persistenc_6aea閱讀 124,470評論 2 7
  • 16宿命:用概率思維提高你的勝算 以前的我是風(fēng)險厭惡者耗美,不喜歡去冒險京髓,但是人生放棄了冒險,也就放棄了無數(shù)的可能商架。 ...
    yichen大刀閱讀 6,041評論 0 4