開發與維運

mPaaS最佳實踐之《Android Native crash處理》

一 背景

目前 mPaas Android是使用的是Crash SDK對閃退進行的處理,CrashSDK 是 Android 平臺上一款功能強大的崩潰日誌收集 SDK,有著極高的崩潰收集率和完整、全面的崩潰日誌信息,生成的日誌內容非常利於問題的跟進和解決。在我們的日常運維中,經常遇到一些閃退,無法直接從閃退堆棧看到原因,尤其是一些非Java的Native的閃退,這裡分享下在mPaas框架下怎麼使用Crash SDK對閃退進行分析。

二 閃退報文分析工具介紹

對於mPaas的用戶,從MAS上閃退分析平臺導出的一般是原始的閃退信息,閃退信息比較多,如果直接閱讀會比較困難,使用者可以通過下載Chrome的插件LogAnalyzer,LogAnalyzer會將Crash SDK生成的日誌文本內容轉化成可視效果較強的 HTML 頁面展現,功能還是很強大的,主要包含:

1. 高亮顯示日誌中重點信息,並使用不同顏色區分;

2. 支持日誌內容整體結構預覽,快速定位重點內容;

3. 常見崩潰原因提醒;

安裝好chrome插件後,還需要做以下配置

1. 修改閃退文件後綴為 .txt

由於MAS上默認下載的文件後綴是.dat,需要改為.txt,否則 LogAnalyzer 會不識別

2. 修改插件配置

由於 Chrome 默認權限限制,任何 Chrome 插件默認都不能訪問文件網址,需要在 Chrome 插件中進行如下操作。

  1. 打開 Chrome 插件管理頁面 chrome://extensions/
  2. 找到 LogAnalyzer 插件,點擊 “詳細信息" 進入設置:

image

  1. 找到允許訪問文件網址選項,並勾選:
  2. 打開或者刷新日誌頁面,LogAnalyzer 就生效了。

3. 生效效果

把日誌文件直接拖到chrome後,可以看到右邊插件生效後,可以通過不同顏色顯示閃退信息的各個字段

首次打開後的使用說明如下:

image

正常查看閃退截圖如下:

image

三 閃退分析舉例

我們經常在日常運維中遇到一些非Java的Native模塊閃退,比如UC。這種時候很多時候只能去聯繫UC團隊進行支撐,其實很多場景下,閃退的根因並不是UC,只是最後的閃退點在UC。以我最近日常運維中比較常遇到的UC內核的閃退為例,對一些案例的處理分享如下。

1. java空指針導致UC閃退

我們在閃退點上可以看到以下閃退(已經隱藏客戶apk相關信息),如果只是從這看我們暫時沒有任何線索,我們繼續往下看日誌

image

當看到logcat節點信息的時候,我們發現了線索,首先我們看到關鍵字:begin to generate native report, 表示當前是閃退日誌上報的日誌,我們在往前看,logcat節點裡打印了異常堆棧信息,從堆棧信息可以看到,是由於precreate操作觸發了底層的空指針,從而導致初始化異常,最後觸發了閃退。解決方案就是臨時關閉預創建,從而規避了閃退。

image

從上面的案例我們可以看出,

  1. Native的閃退不一定是Native模塊的原因導致的,有可能是由於java導致的異常,從而導致Native閃退
  2. begin to generate native report 附近可以看閃退相關的logcat信息,協助定位閃退的一些上下文日誌。

2. 上層OOM導致UC閃退

首先我們看上報的閃退點的日誌如下圖所示,閃退在了RenderThread裡,也是毫無頭緒。

image

我們繼續硬著頭皮往下看,在logcat節點裡查找begin to generate native report上報節點,我們看到了大量的底層OOM的異常日誌,基本大概率確定是OOM的原因了。剩下的就是查找OOM是哪裡觸發的。

image

點擊閃退裡的內存節點,基本原因就比較清晰了,當前手機的vmsize基本已經到最大了,我們知道對於 32 位的進程,APP 可使用的 VmSize 最大為 3GB,不過當運行在 64 位 CPU 上時,VmSize 最大可超過 3GB,接近 4GB。但是由於內核需要佔據一部分,以及不同的ROM版本的差別,我們發現有以下規律:android  8.1.0 及之後的系統,大部分 native oom crash 發生時 vmSize 分佈在 3.5 - 3.9 G 的位置,相對較為集中。所以下面的案例的解決思路就變成了怎麼解決OOM了。

image

3. FD誤關導致UC閃退

上報的日誌如下圖所示,我們大概只能看出SIGILL有可能是主動崩潰,崩潰ILL_ILLOPC表示非法操作。

image

然後我們繼續看logcat節點的begin to generate native report, 基本確認原因是因為uc使用的FD對象被其他程序關閉。

image

隨後UC提供了帶FDscan的工具包,通過我們復現後發現,是由於UC調用shouldIntercept回調的輸入流對象被其他模塊close掉了,導致UC使用的時候發現FD對象已經被關閉,從而做了崩潰處理。最後的處理方案就變成了用戶解決其他模塊的誤關FD的問題。

image

四 總結

綜合以上的case分析,在遇到Native模塊閃退的時候,一般如果從直接的閃退堆棧看不出原因的時候,不要心急,可以搜索begin to generate native report 找到崩潰上下文,多看看logcat閃退上下文的日誌,會有一些收穫,同時對於oom類型的問題,可以結合當前內存統計來看。

Leave a Reply

Your email address will not be published. Required fields are marked *