精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

二十萬分之一幾率:if語句變do-while卡死問題分析

開發 前端
某次灰度發布之后沒多久就收到線上ANR告警,經排查定位到是某個頁面onCreate方法執行太久導致,而火焰圖中的耗時堆棧指向了我們用于監控頁面啟動速度的一段插樁代碼,反編譯Apk之后發現本該是if語句的代碼竟變成了一個do-while語句,形成了死循環最終導致主線程卡死。

一、背景

某次灰度發布之后沒多久就收到線上ANR告警,經排查定位到是某個頁面onCreate方法執行太久導致,而火焰圖中的耗時堆棧指向了我們用于監控頁面啟動速度的一段插樁代碼,反編譯Apk之后發現本該是if語句的代碼竟變成了一個do-while語句,形成了死循環最終導致主線程卡死。

此后每構建二、三十次都會復現一次該問題,且每次的異常頁面,異常方法完全隨機。

圖片圖片

二、問題分析

if和do-while兩個完全不相干的語句為什么出現互相轉化的情況?在jadx反編譯而來的smali代碼中不難看出,if語句對應的標簽正常情況下應該指向的是return語句,和Java源碼中if語句塊后面緊跟著return語句對應。而異常情況下標簽跑到了整個函數的開頭,故被jadx翻譯成了do-while,因此問題的關鍵就在這個label上面。

圖片圖片

初步分析

出現此問題的這段插樁代碼出自我們的APM頁面啟動監控,原本是插樁在Activity和Fragment的onCreate等關鍵生命周期中用于耗時統計。其所在的類是由我們自定義的插樁plugin weaver所生成(基于byteX開發的一個plugin,支持插入,代理和替換等自定義的插樁行為)。

因此我們要對從該plugin所在的byteX transform開始,直到最終產出dex文件的R8 transform結束這期間的所有transform挨個分析。

由于問題偶現,且每次異常的類和方法完全隨機,說明大概率是一個多線程并發讀寫的問題,因此我們在分析過程中會需要重點關注涉及并發讀寫的邏輯。

分析R8

我們在輸入給R8的jar包中找到了這個異常類的class文件,這里可以看到jadx反編譯這個方法會失敗,看class字節碼中if語句跳轉指向的標簽L29,但是函數中并沒有定義L29指向的是哪里,并且smali視圖下查看可以看到if語句指向的標簽在整個函數體中也沒有聲明,但是前面反編譯DEX文件得到的結論是標簽有聲明但是在函數體的第一行,兩者不一致,說明R8可能在執行過程中編輯了字節碼導致異常。

(這里我們早期誤以為標簽丟失并不會導致語句變化這種程度的錯誤,因此直接將范圍鎖定在了R8,雖然后續證明了此問題與R8無關,但這段分析也為最終解開謎底提供了關鍵線索)

圖片圖片

圖片圖片

環境準備

R8目前已經不再單獨提供jar包,而是一同打包在AGP中,且開啟了混淆,因此想要調試/修改代碼就需要自行clone源碼,切到自己項目AGP版本對應的git tag來構建R8.jar并指定,具體操作可以參考R8的git倉庫中描述:https://r8.googlesource.com/r8

階段產物分析

目前的R8是由早期的D8融合了一系列的包體/性能優化的操作而來,dx負責將jar包整合壓縮成DEX文件,它相對于后來新增的編譯優化操作來說出現問題的概率更低,因此我們優先關注R8中涉及對字節碼進行編輯的優化功能。

由于R8在輸入了jar包之后一直在內存中進行操作,并無中間產物,因此我們需要在相關功能的開始結束點手動將內存中所有由自定義weaver plugin生成的class(有統一的后綴名)寫到文件并保存。

圖片圖片

圖片圖片

在多次打包復現問題之后,對階段產物進行分析并未發現異常方法的字節碼有任何變動,直到dx這一步,我們發現if語句在class字節碼中跳轉到指定標簽的行為,在dex文件的smali字節碼中被編譯成了跳轉到指定的函數偏移量。

而之前class字節碼中if語句指向的label找不到聲明的問題,在smali中表現為直接將函數偏移量設為默認值0X00,正好是函數體的第一行,和一開始反編譯apk得到的結果吻合,這也就解釋了為什么if語句最終會變成一個do-while語句。

圖片圖片

小結

至此,我們已經知曉為什么if語句會變成毫不相干的do-while語句,同時也排除了R8的嫌疑,接下來就是要繼續回溯transform,排查為什么class字節碼中if語句指向的標簽的聲明會丟失。

分析weaver

在回溯排查完所有途徑transform的產物之后確認這個異常的方法在一開始weaver生成他時就已經是異常狀態,因此問題范圍鎖定到此plugin。

在繼續分析問題之前我們來了解下weaver的插樁原理:

weaver插樁原理

weaver基于byteX實現了一些自定義的插樁行為,這次出問題的是insert行為,也就是在目標函數開頭插入代碼的模式,其實現原理是預先寫好要插樁的代碼,在plugin執行期間會用ASM的classNode讀取這個類,并將其中的方法復制到一個新建的內部類中,這個內部類會被添加到在注解中指定的目標類中,再在目標類的生命周期函數中調用這個內部類對應的方法即可完成對生命周期的插樁。

圖片

走碼分析

雖然我們已經確認是weaver在生成內部類中方法時出現異常,但是生成的過程是從0到1,此時再去加日志打印class字節碼分析中間產物已經沒有意義,并且由于其極低的復現概率,我們也無法在本地做調試分析。

遂走碼分析,最后發現在從舊方法中復制方法提供給內部類的過程中,出現了ASM版本不一致的問題,由于整個byteX組件全局指定了ASM的版本是9,但是weaver中使用了ASM9的methodNode去clone出一個指定為ASM5的methodNode,但是很遺憾這并不是根因,在修正版本后依舊會復現問題。

圖片圖片

圖片圖片

我們目前已知的只有class字節碼中if語句指向的label沒有聲明,遂猜測是methodNode的指令鏈表中丟失了labelNode,但添加了相應的檢測邏輯之后并未命中,故排除labelNode丟失的可能。

關鍵線索缺失

前文中提到過推測這個問題和多線程有關,因此理論上在本地固定輸入輸出,并用大量線程并發死循環跑是能夠復現問題從而debug找到根因的,但是苦于沒有明確的檢測邏輯,即不知道這個methodNode在什么狀態下才算異常,哪怕問題復現了也無法斷點。

逆向分析異常字節碼

當務之急是找到合適的異常字節碼檢測手段,但是在常規思路都碰壁時,不妨用逆向思維試試,于是把異常的class文件直接用ASM的classNode類讀取到內存,仔細觀察異常方法和正常方法的指令鏈表中labelNode是否有什么不一樣。最終發現異常methodNode的指令鏈表中,jumpNode持有的labelNode和鏈表中的labelNode不是同一個對象(正常情況下是)。

帶著這個逆向得到的結論,再正向去驗證他,即編碼實現主動將某個方法的labelNode給替換成新的對象,再輸出為class文件,發現和前面得到的異常class完全一致,至此我們就得到了一個準確的異常檢測邏輯。

圖片圖片

帶著前面得到的精準檢測邏輯,我們在本地寫demo開16線程并發,瞬間就復現了此問題,隨后順著這個線索走碼也找到了問題根因。

這里使用我們正常運行時使用的forkjoinpool,并發死循環執行前面提到的methodNode復制過程,模擬正常構建過程的并發度,最終得出結果是大約每執行20w次可以復現一次問題,除以我們App中相關方法的量級,正好和之前約每20次~30次構建復現一次的頻率吻合。

圖片圖片

圖片圖片

小結

至此我們已經定位到了引起問題的代碼,也通過多種手段驗證了根因就是多線程復制methodNode,但穩妥起見還是要刨根問底弄明白并發復制到底是怎么引起的labelNode對象被替換,防止還有更深層次的問題被掩蓋。

揭露謎底

ASM方法復制原理

methodNode復制流程圖如下:

圖片圖片

ASM的methodNode類,通過其accept方法可以將這個方法復制給一個methodVIsitor,通常情況下只會使用一次,如果有1次以上的復制行為,就會在復制之前將指令鏈表中的labelNode中記錄跳轉地址的label對象置為null。

(clone方法理應是創建一個全新的對象,不應該和舊對象有任何共用的數據,ASM這里的處理沒問題,但是沒有適配多線程的情況)

圖片圖片

圖片圖片

隨后在指令復制的過程中,在遍歷到jump指令(通過持有labelNode來形成指向關系)時,會通過getLabel方法將剛剛被置null的label對象重新new出來,同時再從新的label對象中new一個新的LabelNode交給新的JumpNode。

圖片圖片

圖片圖片

圖片圖片

圖片圖片

等遍歷到對應的LabelNode時,此時getLabel拿到的是剛剛new出來的新Label,同樣的鏈路再走一遍,此時無需再new新的,并且新方法中的JumpNode持有的labelNode也和當前是一個對象。

圖片圖片

圖片圖片

多線程問題根因

至此我們能得知在復制methodNode的過程中,針對labelNode有多次讀寫操作。而weaver為了加快執行速度,對每一個class都單獨安排了一個task,全都提交給一個forkJoinPool來執行,并且按照前面介紹的weaver插樁原理,提前寫好的這個類里的方法,總計會復制成千上萬次,提供給每一個Activity的內部類。因此在多線程高并發執行時就會出現以下順序:

圖片圖片

這樣最終就會出現jumpNode持有的LabelNode和指令鏈表中的LabelNode不一致的問題。

三、修復方案

ASM為了規避同一個methodNode在多次復制時,復制出來的新methodNode的labelNode全都指向同一個對象的問題,加了這個resetLabel的標簽重置邏輯,但是并沒有考慮到多線程并發執行的場景,因此該問題最終加一個類鎖即可解決,放那已上線驗證有效。

圖片圖片

四、總結

這類多線程引起的字節碼異常問題潛伏期可達到數年之久,例如本文遇到的問題在App的頁面量級較低時幾乎不會觸發,但隨著App的業務規模增長,又或是打包機器的一次升級換代,問題就會悄然出現,而他極低的復現概率和隨機性又很容易使其被忽視。

字節碼異常問題在互聯網鮮有參考資料,倘若字節碼損壞直接崩潰還則罷了,遇到這種恰巧能被當成其他語句繼續執行的情況分析起來著實麻煩。因此開發插樁這類涉及代碼編輯操作的plugin,針對"寫”操作務必要慎重開發,重點測試下極端并發的場景。這類問題如果是發生在定時大量推送的活動頁或者熱修sdk之類穩定性兜底的功能,其危害可想而知。

責任編輯:武曉燕 來源: 得物技術
相關推薦

2019-06-19 08:28:18

Windows操作系統Windows 10

2012-05-04 13:17:28

微瘋客棧

2022-04-11 07:11:28

日志輸出代碼業務代碼

2021-12-08 10:43:33

AI 數據人工智能

2021-12-10 09:50:22

數據腦神經3D

2020-07-23 08:18:27

C語言執行循環體條件

2022-10-28 07:38:06

Javawhile循環

2024-11-07 13:07:47

2021-09-13 07:58:52

考試算法PAT

2022-01-17 21:08:54

Python 循環結構

2019-10-29 15:01:48

BAT運維監控

2013-05-02 16:18:43

2022-08-29 11:00:32

區塊鏈加密貨幣

2022-09-14 18:24:19

AB實驗平臺自動化

2010-03-24 14:06:04

APC

2009-02-25 08:50:45

Mini9戴爾Linux

2009-12-09 09:50:15

上網本Linux

2025-05-14 08:00:00

AIGenAI人工智能

2013-04-19 10:48:42

點贊
收藏

51CTO技術棧公眾號

精品国产不卡一区二区| 国产欧美黑人| 日韩和欧美一区二区三区| 神马国产精品影院av| 中文字幕 91| 日本在线视频www鲁啊鲁| 成人h精品动漫一区二区三区| 97福利一区二区| 美国美女黄色片| jizz久久精品永久免费| 日本精品一区二区三区高清| 欧美在线free| 精品粉嫩超白一线天av| 妞干网在线免费视频| 成人短视频在线观看| 91影院在线观看| 成人免费在线视频网址| www.国产色| 欧美日韩亚洲一区| 中文字幕在线国产精品| 亚洲av成人片无码| 一区在线不卡| 在线看不卡av| 红桃av在线播放| 肉肉视频在线观看| 国产精品乱码久久久久久| 韩国成人动漫在线观看| 国产美女无遮挡永久免费| 成年人视频在线看| 神马香蕉久久| 欧美成人午夜电影| 日日干日日操日日射| 免费电影日韩网站| 亚洲成年人网站在线观看| 午夜在线视频免费观看| аⅴ资源新版在线天堂| 91欧美一区二区| 中文国产成人精品久久一| 成年女人免费视频| 国产成人77亚洲精品www| 狠狠干狠狠久久| 正在播放国产精品| av在线首页| 国产无人区一区二区三区| 久久99精品久久久久久青青日本| 国产成人精品一区二区无码呦| 日韩激情视频在线观看| 欧美在线欧美在线| 五月婷婷中文字幕| 亚洲精品九九| 欧美日韩第一视频| 18岁成人毛片| 中文字幕亚洲综合久久五月天色无吗'' | 激情五月激情综合网| 国产精品免费网站| 中文字幕av片| 久久激情五月婷婷| 成人免费网站在线看| 一区二区三区精| 精品亚洲aⅴ乱码一区二区三区| 成人免费网站在线| 精品黑人一区二区三区在线观看 | 国产精品视频久久久久| 国产天堂第一区| 蜜桃传媒麻豆第一区在线观看| 国产精品pans私拍| 国产男人搡女人免费视频| 欧美亚洲一级| 国产欧美一区二区| 国产精品热久久| 国产福利91精品一区二区三区| 97伦理在线四区| 成人激情四射网| 成人激情免费网站| 久久av一区二区三区亚洲| 秋霞av在线| 亚洲国产精品99久久久久久久久 | 欧美久久一二区| 精品国产午夜福利在线观看| 嗯用力啊快一点好舒服小柔久久| 亚洲国产欧美一区二区丝袜黑人| 日韩av在线看免费观看| 日韩大片在线播放| 美女国内精品自产拍在线播放| www.99re7| 国产亚洲高清视频| 国产精品自拍偷拍视频| www.激情五月| 久久久久久久免费视频了| 在线观看成人一级片| 日韩另类在线| 日韩欧美在线视频免费观看| 少妇一级淫免费播放| 人人爱人人干婷婷丁香亚洲| 亚洲精品成人久久| 懂色av粉嫩av浪潮av| 午夜精品国产| 国产91在线高潮白浆在线观看| 中文字幕在线2019| 成人午夜短视频| 水蜜桃一区二区三区| 人妖欧美1区| 欧美午夜激情视频| 古装做爰无遮挡三级聊斋艳谭| 粉嫩的18在线观看极品精品| 国产亚洲一级高清| 久久久久香蕉视频| 蜜臀91精品一区二区三区| 国产精品一区二区你懂得| 99re在线视频| 色综合天天做天天爱| 黑人玩弄人妻一区二区三区| 色综合狠狠操| 51视频国产精品一区二区| 国产精品美女一区| 国产日韩欧美制服另类| 欧美成人精品免费| 99精品女人在线观看免费视频| 日韩高清人体午夜| 亚洲女人毛茸茸高潮| 久久久久久穴| 国产一区自拍视频| 宅男网站在线免费观看| 欧美色图在线观看| 狠狠人妻久久久久久综合蜜桃| 欧美激情综合| 91在线观看免费高清完整版在线观看| 国产黄色片在线观看| 精品久久久久久国产| 亚洲熟女一区二区三区| 久久久久国产| 国产精品情侣自拍| 国产免费视频在线| 欧美午夜精品久久久久久久| 69亚洲乱人伦| 国内一区二区三区| 99re在线播放| 羞羞视频在线观看免费| 5月丁香婷婷综合| 国精产品久拍自产在线网站| 日韩av一二三| 亚洲国产精品综合| 97久久网站| 一本一道久久a久久精品逆3p| 国产成人无码一区二区在线播放| 91在线视频免费91| av之家在线观看| 日韩电影在线观看完整免费观看| 国语自产精品视频在免费| 国产成人无码www免费视频播放| 亚洲另类在线一区| japan高清日本乱xxxxx| 久久精品一区二区不卡| 亚洲aⅴ日韩av电影在线观看| 欧美精品电影| 欧美一级日韩一级| 欧美高清视频一区二区三区| 国产传媒一区在线| 日韩av中文字幕第一页| 国产精品中文字幕制服诱惑| 97高清免费视频| 色哟哟在线观看| 在线观看中文字幕不卡| 刘亦菲国产毛片bd| 精久久久久久久久久久| 97av中文字幕| 六月丁香久久丫| 国产成人精品一区二区| 在线观看免费网站黄| 91精品国产福利| 麻豆一区二区三区精品视频| 97se狠狠狠综合亚洲狠狠| 丁香啪啪综合成人亚洲| 久久国产亚洲精品| 91九色在线视频| a级大胆欧美人体大胆666| 日韩精品免费在线视频观看| 国产一级片毛片| 中文久久乱码一区二区| 日本黄色一级网站| 亚洲一区不卡| 亚洲欧洲精品在线| 一区视频网站| 热久久这里只有| 黄色精品免费看| 亚洲国产精久久久久久久| 青青国产在线视频| 亚洲精品国产a久久久久久| 国产不卡一二三| 麻豆精品视频在线观看免费| 日本天堂免费a| 国产99久久久国产精品成人免费| 国产男人精品视频| 97人澡人人添人人爽欧美| 尤物yw午夜国产精品视频明星| 精品人妻午夜一区二区三区四区| 一本到高清视频免费精品| 我家有个日本女人| 国产亚洲精品超碰| 一本色道久久hezyo无码| 麻豆精品一二三| 欧美s码亚洲码精品m码| 亚洲国产老妈| 日本三级中国三级99人妇网站| 日韩在线观看中文字幕| 国产精品老女人精品视频| 2021天堂中文幕一二区在线观| 中文字幕日韩高清| 四虎在线观看| 欧美精品三级日韩久久| 久久久久久91亚洲精品中文字幕| 亚洲精品写真福利| 黄免费在线观看| 成a人片亚洲日本久久| 午夜国产福利在线观看| 日韩高清不卡在线| 国产精品999视频| 欧美大片一区| 一区二区国产日产| 国产探花在线精品| 国产尤物99| 国产成人一二| 91久久国产自产拍夜夜嗨| 欧美日韩尤物久久| 青草成人免费视频| 91九色porn在线资源| 欧美成人h版在线观看| www.亚洲资源| 亚洲嫩模很污视频| 五月激情六月婷婷| 精品国精品自拍自在线| av 一区二区三区| 91麻豆精品国产91久久久久 | 国产不卡人人| 久久久久在线观看| 美足av综合网| 欧美激情欧美激情| 色呦呦在线观看视频| 超碰97人人做人人爱少妇| 欧洲不卡av| 一本一道久久a久久精品逆3p | 99久久夜色精品国产亚洲| 欧美日韩亚洲综合| 一区二区小视频| 欧美亚洲高清一区| 亚洲精品一区二区二区| 欧美亚洲综合网| 中文字幕在线视频免费| 欧美日韩亚洲综合在线 欧美亚洲特黄一级| 国产精品免费无遮挡无码永久视频| 欧美性xxxxxxx| wwwwww在线观看| 欧美视频在线观看一区| 92久久精品一区二区| 91精品国产高清一区二区三区蜜臀| 国产视频一区二区三| 精品精品国产高清a毛片牛牛| 噜噜噜久久,亚洲精品国产品| 亚洲高清色综合| 能在线看的av| 一区二区三欧美| 日本最新在线视频| 欧美成人免费在线视频| 日韩专区av| 欧美中文字幕在线| 成人精品一区二区三区电影| 国产日韩av在线播放| 亚洲图色一区二区三区| 久久婷婷人人澡人人喊人人爽| 国产一区二区三区四区| 一区二区三区我不卡| 欧美激情四色| 亚洲欧洲日产国码无码久久99 | 亚洲av无码成人精品区| 成人精品在线视频观看| 播金莲一级淫片aaaaaaa| 国产免费成人在线视频| 久久国产精品国语对白| 亚洲综合在线视频| 国产精品久久久久久久久久精爆| 欧美日韩国产免费一区二区| 午夜精品久久久久久久爽| 日韩毛片中文字幕| 香蕉视频在线看| 欧美激情二区三区| 激情开心成人网| 成人在线中文字幕| 猫咪成人在线观看| 亚洲亚洲精品三区日韩精品在线视频| 午夜国产精品视频免费体验区| 日韩av一二三四| 成人综合婷婷国产精品久久免费| 非洲一级黄色片| 亚洲高清免费视频| 在线观看免费黄色小视频| 精品国产污网站| 日本免费视频在线观看| 777精品视频| 成人黄色91| 欧美一区二区视频17c| 欧美日韩一视频区二区| 最近中文字幕一区二区| 成a人片亚洲日本久久| 91麻豆免费视频网站| 色噜噜狠狠成人网p站| 亚洲精品久久久久久久久久久久久久| 国产亚洲精品日韩| 黄色羞羞视频在线观看| 国产精品视频xxxx| 日韩av黄色在线| 四虎4hu永久免费入口| 日韩影院在线观看| 国产伦精品一区二区免费| 亚洲视频狠狠干| 做爰视频毛片视频| 亚洲日本欧美中文幕| 第一福利在线视频| 99国产盗摄| 亚洲大全视频| 九九热免费在线观看| 久久精品在线观看| 久久久久久久极品| 日韩精品一区二区在线观看| 黄色一级片在线观看| 国产精品日韩电影| 国产精品羞羞答答在线观看| 国产黄色片免费在线观看| 国产精品一品二品| www.av免费| 欧美日韩午夜在线| 福利小视频在线观看| 人人澡人人澡人人看欧美| 欧洲亚洲成人| 亚洲不卡中文字幕无码| 成人av网站在线观看免费| 久草视频在线资源站| 91麻豆精品国产自产在线观看一区 | 亚洲最大中文字幕| 成人教育av| 免费一区二区三区在在线视频| 国产女优一区| 丰满少妇一区二区| 欧美性xxxx极品hd欧美风情| 四虎国产精品永远| 欧美在线视频观看| 伊人久久大香线蕉av不卡| 国产在线青青草| 久久久久成人黄色影片| 成年人av网站| 一区二区国产精品视频| 欧美jizz18| 老汉色影院首页| 国产一区不卡视频| 久久精品一级片| 亚洲国产精品高清久久久| 欧美三级网站| 欧美日韩在线观看一区二区三区| 日韩在线观看一区二区| 亚洲女同二女同志奶水| 欧美一区午夜视频在线观看| 色呦呦网站在线观看| 精品久久久久久综合日本| 久久国产高清| 91成人精品一区二区| 3d成人h动漫网站入口| 青青草视频在线免费直播| 精品一区二区日本| 天堂资源在线中文精品| 91狠狠综合久久久久久| 日韩一区二区在线观看| segui88久久综合| 日韩欧美电影一区二区| 激情欧美一区二区三区在线观看| 久久久久久久久久网站| 亚洲国产精品999| 九七电影院97理论片久久tvb| 午夜啪啪福利视频| 91在线国内视频| 91国产免费视频| 久久久久久综合网天天| 免费av一区| 成人三级做爰av| 日本韩国欧美一区| 国产精品实拍| 狼狼综合久久久久综合网| 久久精品国产999大香线蕉| 国产中文字字幕乱码无限| 国产一区二区三区在线视频| 亚洲不卡视频| av无码精品一区二区三区| 一区二区三区影院| 黄上黄在线观看| 动漫美女被爆操久久久| 日韩福利电影在线观看| 久久久久久天堂| 日韩在线免费观看视频| 久久久亚洲欧洲日产| av噜噜在线观看| 色婷婷综合五月| 日本中文字幕中出在线|