精品欧美一区二区三区在线观看 _久久久久国色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技術棧公眾號

国产一区二区色| 91精品中文字幕一区二区三区 | 亚洲我射av| 亚洲图片欧美一区| 日韩av在线电影观看| 国产按摩一区二区三区| 国产精品亚洲欧美| 久久资源免费视频| 亚洲精品国产一区黑色丝袜 | 人禽交欧美网站| 久久久久久91| 黄色精品视频在线观看| 婷婷成人影院| 日韩欧美激情一区| 丰满少妇在线观看| 美女高潮视频在线看| 亚洲图片你懂的| 久久精品magnetxturnbtih| 国产精品无码一区二区桃花视频 | 成人精品影院| 亚洲精品成人久久电影| 日本成人xxx| 日本在线中文字幕一区二区三区| 亚洲已满18点击进入久久| 亚洲精品欧美精品| 国产香蕉视频在线看| caoporm超碰国产精品| 91免费版网站入口| 中文字幕男人天堂| 日韩专区在线视频| 欧洲精品在线视频| 国产成人在线观看网站| 欧美日韩亚洲三区| 欧美成人午夜免费视在线看片| 人人妻人人澡人人爽| 天堂俺去俺来也www久久婷婷| 精品国精品自拍自在线| 国产不卡的av| 美国十次综合久久| 56国语精品自产拍在线观看| 特级丰满少妇一级| 欧美色片在线观看| 欧美日韩在线电影| 中文字幕亚洲乱码| 国产亚洲精品精品国产亚洲综合| 欧美羞羞免费网站| 天天爱天天操天天干| 成人日韩精品| 欧美性生活久久| 青青在线视频免费| 香蕉成人av| 欧美亚洲日本国产| 浓精h攵女乱爱av| 国产第一精品| 在线不卡一区二区| 国产黄色一级网站| 欧美人与性动交α欧美精品图片| 国产精品嫩草99a| 在线精品日韩| jizzjizz亚洲| 亚洲一区在线视频观看| www.射射射| 狠狠操一区二区三区| 欧美性xxxxxxxxx| 欧美一级片中文字幕| 亚洲a∨精品一区二区三区导航| 91极品视觉盛宴| 午夜免费看视频| 精品中文视频| 亚洲电影在线观看| 中日韩精品一区二区三区| 欧美裸体在线版观看完整版| 日韩中文字幕精品| 欧美精品一区二区蜜桃| 99在线|亚洲一区二区| 国产精品99久久99久久久二8| 中文字幕精品无码亚| 国产激情视频一区二区三区欧美| 国产精品久久久久免费| 你懂的免费在线观看| 国产精品美女久久久久久久网站| 成人在线免费高清视频| 久草在线资源站手机版| 欧美日韩成人综合| 国产免费a级片| 啪啪亚洲精品| 欧美老女人xx| 无码人妻精品一区二区蜜桃色欲| 国产最新精品免费| 久99久视频| aⅴ在线视频男人的天堂 | 国精产品视频一二二区| 欧美日韩免费| 国产精品美女免费| 刘玥91精选国产在线观看| 久久丝袜美腿综合| 三级在线免费观看| 欧美亚洲大片| 精品久久久三级丝袜| 中文字幕黄色网址| 亚洲少妇在线| 亚洲sss综合天堂久久| 天堂a√中文在线| 亚洲精品久久嫩草网站秘色| 国产91对白刺激露脸在线观看| 伊人亚洲精品| 亚洲九九九在线观看| 男人与禽猛交狂配| 日韩av一二三| 久久久久欧美| 污片在线免费观看| 欧美人与z0zoxxxx视频| 国产精品jizz| 黄色成人在线网址| 成人免费网站在线看| 国产三区四区在线观看| 亚洲电影在线播放| 午夜影院免费观看视频| 日韩免费特黄一二三区| 日韩av不卡在线| 狠狠综合久久av一区二区| 亚洲欧美日韩久久| 日本肉体xxxx裸体xxx免费| 婷婷综合成人| 国内精品久久久久久久久| 国产ts人妖调教重口男| 综合久久久久久| 日本中文字幕精品—区二区| 欧美日韩精品在线一区| 国产91色在线播放| 秋霞av在线| 午夜精品久久久久久久99樱桃| 国产一级片中文字幕| 亚洲h色精品| 成人午夜在线观看| 日本免费中文字幕在线| 欧美久久免费观看| 五月婷婷六月香| 日本aⅴ亚洲精品中文乱码| 噜噜噜噜噜久久久久久91| 成人观看网址| 精品小视频在线| 欧美日韩精品区| av亚洲精华国产精华| 国产原创中文在线观看| 国产欧美三级电影| 欧美—级a级欧美特级ar全黄| www日本在线| 亚洲一区二区免费视频| 中文字幕在线视频播放| 日韩视频精品在线观看| 免费看污久久久| 无人区在线高清完整免费版 一区二| 亚洲欧美色图片| 波多野结衣电车| 欧美激情一区二区三区| 久久99爱视频| 欧美在线高清| 成人av电影免费| 黄色18在线观看| 精品丝袜一区二区三区| 成人h动漫精品一区二区下载| 国产日韩精品一区二区三区| 国产日韩欧美久久| 国产综合视频| 久久精品一二三区| 99只有精品| 久久久国产精品一区| 蜜桃视频污在线观看| 欧美日韩精品在线观看| 欧美三级视频网站| 国产精品亚洲成人| 日韩人妻精品无码一区二区三区| 红桃成人av在线播放| 成人午夜在线观看| 樱花草涩涩www在线播放| 最近2019年好看中文字幕视频| 99久久久国产精品无码免费| 亚洲午夜一二三区视频| 丁香激情五月少妇| 国产成人免费视频| aa免费在线观看| 中文字幕亚洲精品乱码| 久久久神马电影| 色狠狠一区二区三区| 午夜精品一区二区三区视频免费看 | 天堂电影一区| 日日噜噜噜夜夜爽亚洲精品 | 91亚洲精品在看在线观看高清| 欧美高清电影在线看| 欧美成熟毛茸茸| 欧美一级在线免费| 亚洲色成人www永久网站| 亚洲免费观看高清完整版在线观看熊| 91丝袜在线观看| 狠狠色丁香婷婷综合| 国产免费黄色av| 欧美+日本+国产+在线a∨观看| 欧美激情第一页在线观看| 国产精一区二区| 国产精品海角社区在线观看| 激情av在线播放| 黄色三级视频在线| 精品久久不卡| 古典武侠综合av第一页| abab456成人免费网址| 欧美激情一区二区三区成人| 在线播放毛片| 亚洲欧美日韩一区二区在线 | 日韩一区二区三区在线视频| 中文字幕在线观看视频免费| 精品国产视频| 国产精品永久在线| 在线天堂资源| 久久久久久尹人网香蕉| 黄色网址视频在线观看| 这里精品视频免费| 欧美日韩激情视频一区二区三区| 日韩免费视频线观看| 91精品人妻一区二区三区果冻| 懂色av影视一区二区三区| 久久久精品国产sm调教| 国产综合精品| 欧美极品视频一区二区三区| 99精品国产一区二区三区2021| 国产日产久久高清欧美一区| 久久av高潮av无码av喷吹| 91蝌蚪国产九色| 野战少妇38p| 国产不卡在线一区| 国产精品igao网网址不卡| 韩国一区二区在线观看| 91亚洲精品久久久蜜桃借种| 爱福利在线视频| 亚洲午夜小视频| 深夜福利免费在线观看| 亚洲国产欧美在线成人app| 亚洲精品国产片| 精品av综合导航| 欧日韩在线视频| 亚洲电影天堂av| 手机在线观看毛片| 亚洲国产毛片完整版| 午夜一区在线观看| 亚洲精品综合久久中文字幕| 你懂的在线观看| 一区二区三区美女xx视频| 成年人在线看| 日日狠狠久久偷偷四色综合免费| 免费观看成人高潮| 欧美成人h版在线观看| 91三级在线| 久久久女女女女999久久| 欧亚在线中文字幕免费| 国产成人一区二| 看片一区二区| 亚洲专区在线视频| 91精品丝袜国产高跟在线| 国产精品免费区二区三区观看| 极品束缚调教一区二区网站| 极品日韩久久| 精品一区二区三区在线| 一区二区免费在线观看| 在线看片不卡| 国产伦精品一区二区三区四区视频_| 欧美专区一区二区三区| 亚洲天堂av线| 国产一区二区三区日韩| 影音先锋资源av| 久久精品一区二区三区四区| 男人晚上看的视频| 性久久久久久久久久久久| 老熟妇仑乱一区二区av| 欧美日韩免费不卡视频一区二区三区 | 亚洲小说欧美另类婷婷| 成人av一级片| 国内成人精品2018免费看| 喷水视频在线观看| 国产精品污网站| 国产性生活网站| 色偷偷88欧美精品久久久| 国产熟女一区二区三区四区| 精品视频在线观看日韩| 黄色动漫在线观看| 97视频在线免费观看| 午夜精品久久久久久毛片| 国产精品一区二区三区四区五区| 国产一区二区三区四区大秀| 精品人妻人人做人人爽| 久久亚洲国产精品一区二区| 视频区 图片区 小说区| 久久久电影一区二区三区| 在线免费观看亚洲视频| 色婷婷综合久色| 亚洲av无码片一区二区三区| 国产一区二区三区在线视频| 国产桃色电影在线播放| 国产日本欧美一区二区三区在线 | 精品视频在线一区二区在线| 国产成人免费电影| 首页国产精品| 男人的天堂99| 丁香啪啪综合成人亚洲小说 | 午夜一区二区三区视频| 亚洲一区二区视频在线播放| 日韩精品极品毛片系列视频| 性xxxfreexxxx性欧美| 国产在线精品播放| 尤物tv在线精品| 成年人午夜视频在线观看| 国产乱码字幕精品高清av| 精品无码国产污污污免费网站 | 欧美黄色影院| 欧美一级爱爱视频| 狠狠色丁香久久婷婷综| 精品日韩在线视频| 91久久免费观看| 午夜性色福利影院| 97免费在线视频| heyzo欧美激情| 久久久天堂国产精品| 国产在线精品一区二区不卡了 | 欧美性感美女h网站在线观看免费| 国产婷婷在线视频| 日韩一区二区福利| 国产一区二区三区四区五区3d| 日本在线高清视频一区| 性色一区二区三区| 一级欧美一级日韩片| 香蕉av福利精品导航 | 亚洲欧美精品一区二区| 九色porny自拍视频在线观看| 国产精品sss| 很黄很黄激情成人| 一级黄色片毛片| 亚洲第一福利视频在线| 国产91免费看| 国内成人精品视频| 开心激情综合| 黄色成人在线看| 91美女在线视频| 免费看日批视频| 伊人伊成久久人综合网站| 51一区二区三区| 一区二区三区在线观看www| 奇米一区二区三区av| 永久免费未视频| 日韩一区二区在线看片| 7777精品伊久久久大香线蕉语言| 成人香蕉社区| 日韩av在线播放不卡| 成+人+亚洲+综合天堂| 午夜偷拍福利视频| 亚洲精品av在线| 亚洲深夜视频| 青青草成人网| 美女免费视频一区二区| 三级黄色在线观看| 日韩欧美黄色影院| 春色校园综合激情亚洲| 欧美精品免费观看二区| 青青草精品视频| 性欧美疯狂猛交69hd| 精品乱人伦一区二区三区| 欧美久久天堂| 婷婷久久五月天| 国产精品一区二区视频| 日韩欧美中文字幕一区二区| 亚洲欧美在线免费| 婷婷激情成人| 欧美乱大交xxxxx潮喷l头像| 2021国产精品久久精品| 亚洲天堂手机在线| 色综合久久天天综线观看| 欧美做受69| 青青青在线视频免费观看| 亚洲欧美日韩综合aⅴ视频| 五月天婷婷在线观看| 国产欧美在线视频| 亚洲国产综合在线看不卡| 国产中年熟女高潮大集合| 91精品午夜视频| 一个人看的www视频在线免费观看 一个人www视频在线免费观看 | 日韩经典一区二区三区| 欧美影视资讯| 人妻av无码专区| 国产欧美一区二区精品性色 | 亚洲美女av在线播放| 久久一级大片| 99草草国产熟女视频在线| 亚洲综合色婷婷| 国产福利小视频在线观看| 成人免费看片网站| 免费在线看成人av| 国产成人无码精品| 久久午夜a级毛片| 欧美精品一区二区三区中文字幕| 国产伦理在线观看| 欧美日韩一区不卡| 天堂√8在线中文|