通過ANR的堆棧分析,ANR的堆棧都是停在了linklist的contains()函數。通過源碼分析,系統(tǒng)提供的linklist類是通過鏈表的方式實現的。按說應該不會有性能問題,即使一個初級程序員來實現,查詢幾萬條記錄的耗時最多也就是幾十毫秒。作為Android平臺的工具類,性能應該更是頂呱呱。同事通過log日志發(fā)現,系統(tǒng)的linklist在1000條記錄情況下查詢耗時在10毫秒內。自己的手機也沒能復現ANR問題。
下面進入分析階段:
由于bugly的日志上報了App所有多線程堆棧情況(這點很贊),通過堆棧分析,出問題時候,主線程和子線程都在操作linklist,并且為了線程安全,業(yè)務對所有l(wèi)inklist操作都增加了synchronized鎖。通過多個bugly上報的規(guī)律來看,子線程和主線程也都卡在了linklist的操作上。
梳理已知信息:
1、子線程和主線程都卡在了linklist上。
2、子線程和主線程同時進入了不同方法的synchronized內。
分析:
由第一條現象可以嘗試的方向是linklist是否存儲的內容特別多,由于內容超多導致linklist操作耗時超長。(通過代碼分析,linklist內容會定期寫文件且對內容不排重,很有可能造成這種情況)
由第二條現象可以嘗試的方向是單例里持有的linklist的多個同步方法(synchronized),被子線程和主線程同時執(zhí)行,是否和單例創(chuàng)建的安全性有關。(即創(chuàng)建了兩個單例)
追問:
為什么主線程和子線程都卡在了linklist操作上,這么巧?
原因是linklist耗時超長,所以主線程和子線程同時卡在linklist操作的概率就特別大。