APM-監控子線程操作 UI

MainThreadChecker

一款監控子線程操縱 UI 的能力,也可以添加自定義的 API 進行監控(實現在子線程監控某些 API 的時候捕獲具體堆棧信息,幫助定位問題)

背景介紹

可能有些人一直沒有遇到過因爲在子線程操作 UI,導致在開發階段 Xcode console 輸出了一堆日誌,大體如下

其實我們可以給 Xcode 打個 Runtime Issue Breakpoint ,type 選擇 Main Thread Checker, 在發生子線程操作 UI 的時候就會被系統檢測到並觸發斷點,同時可以看到堆棧情況

效果如下

問題及解決方案

上述的功能是在 Xcode 自帶的,連接 Xcode 做調試才具備的功能,線上包無法檢測到。

經過探索 Xcode 實現該功能是依賴於設備上的 libMainThreadChecker.dylib 庫,我們可以通過 dlopen 方法強制加載該庫讓非 Xcode 環境下也擁有監測功能。

另外在監控到子線程調用 UI 調用時,在 Xcode 環境下,會將調用棧輸出到控制檯,經過測試,libMainThreadChecker.dylib 使用的是進行輸出的,由於 NSLog 是將信息輸出到 STDERR中,我們可以通過 NSPipedup2STDERR 輸出攔截,通過對信息的文案的判斷,進而獲取監測到的 UI 調用,最後可以通過堆棧打印出來,就可以幫助定位到具體問題。

libMainThreadChecker.dylib 庫具有侷限性,僅僅對系統提供的一些特定類的特定 API 在子線程調用會被監控到(例如 UIKit 框架中 UIView 類)。 但是某些類有些 API 我們也不希望在子線程被調用,這時候 libMainThreadChecker.dylib是無法滿足的。

libMainThreadChecker.dylib 庫的彙編代碼研究,發現 libMainThreadChecker.dylib 是通過內部 __main_thread_add_check_for_selector 這個方法來進行類和方法的註冊的。所以如果我們同樣可以通過 dlsym 來調用該方法,以達到對自定義類和方法的主線程調用監測。

另外該功能可以在線下 debug 階段開啓,判斷是否是在 Xcode debug 狀態,可以通過蘋果提供的官方判斷方法實現。

dlopendlsym 陌生的小夥伴可以直接看 Apple 官方文檔,這裏不做展開。

APM 合集

對於 APM 感興趣的小夥伴可以查看這篇帶你打造一套 APM 監控系統的文章

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章