鴻蒙HarmonyOS NEXT應(yīng)用崩潰分析及修復(fù)

如何保證應(yīng)用的健壯性,其中一個指標(biāo)就是看崩潰率,如何降低崩潰率,就需要知道存在哪些崩潰,然后對癥下藥,解決崩潰。那么鴻蒙應(yīng)用中存在哪些崩潰類型呢?又改如何解決呢?

故障類型

目前鴻蒙中存在的崩潰主要分為CPP_CRASH、JS_ERROR、OOM、PROCESS_KILL、APP_FREEZE、RESOURCE_LEAK6大類型。

CPP_CRASH類型

主要是進(jìn)程崩潰指C/C++運行時崩潰,主要體現(xiàn)在so相關(guān)的sdk上。

1.空指針解引用 NULL pointer dereference
形如SIGSEGV(SEGV_MAPERR)@0x00000000或r0 r1等傳參寄存器的值為0時應(yīng)首先考慮調(diào)用時是否傳入了空指針

2.結(jié)構(gòu)體/類未初始化指針
形如SIGSEGV(SEGV_MAPERR)@0x0000000c或 r1等傳參寄存器的值為一個很小的值時應(yīng)考慮調(diào)用入?yún)⒌慕Y(jié)構(gòu)體成員是否包含空指針

3.程序主動終止SIGABRT
一般為用戶/框架/C庫主動觸發(fā),大部分場景下跳過C庫/abort發(fā)起的框架庫的第一幀即為崩潰原因
這里主要檢測的是資源使用類的問題,如線程創(chuàng)建,文件描述符使用,接口調(diào)用時序等

4.棧溢出
如遞歸調(diào)用,析構(gòu)函數(shù)相互調(diào)用,特殊的棧(信號棧)中使用大塊棧內(nèi)存

5.多線程操作集合
std的集合為非線程安全,如果多線程添加刪除,容易出現(xiàn)SIGSEGV, 如果使用addr2line后的代碼行與集合相關(guān),可以考慮這個原因

6.不匹配的對象生命周期
如使用裸指針保存sptr類型以及shared_ptr類型

7.返回臨時變量、野指針
如返回棧變量的引用,釋放后未置空繼續(xù)訪問

具體可參考官方
https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/fault-analysis

JS_ERROR類型

當(dāng)未處理的JS異常導(dǎo)致應(yīng)用意外退出時,應(yīng)用會在拋出未處理的異常時崩潰并且會生成對應(yīng)的JS Crash崩潰日志文件。

JS Crash異常根據(jù)不同的異常場景,在 Reason 字段進(jìn)行了分類,分為Error、TypeError、SyntaxError、RangeError等錯誤類型。

自定義 Error 類:Error 是最基本的錯誤類型,其他的錯誤類型都繼承自該類型。Error 對象主要有兩個重要屬性 message 和 name 分別表示錯誤信息和錯誤名稱。程序運行過程中拋出的異常一般都有具體的類型,Error 類型一般都是開發(fā)人員自己拋出的異常。

TypeError(類型錯誤)類:運行時最常見的異常,表示變量或參數(shù)不是預(yù)期類型。

SyntaxError(語法錯誤)類:語法錯誤也稱為解析錯誤。語法錯誤在任何編程語言中都是最常見的錯誤類型,表示不符合編程語言的語法規(guī)范。

RangeError(邊界錯誤)類:表示超出有效范圍時發(fā)生的異常,主要的有以下幾種情況:
數(shù)組長度為負(fù)數(shù)或超長。
數(shù)字類型的方法參數(shù)超出預(yù)定義范圍。
函數(shù)堆棧調(diào)用超過最大值。

ReferenceError - 引用錯誤:引用一個不存在的變量時發(fā)生的錯誤。每當(dāng)我們創(chuàng)建一個變量時,變量名稱都會寫入一個變量存儲中心中。這個變量存儲中心就像鍵值存儲一樣,每當(dāng)我們引用變量時,它都去存儲中找到 key并提取并返回 value。如果我們要找的變量不在存儲中,就會拋出 ReferenceError。

URI Error - URL錯誤:在調(diào)用 URI 相關(guān)的方法中 URL 無效時拋出的異常,主要包括 encodeURI()、decodeURI()、encodeURIComponent()、decodeURIComponent()、escape() 和 unescape() 幾個函數(shù) 。

其中這一類型的bug是最容易修復(fù)的,因為這些往往就是業(yè)務(wù)側(cè)的一些不嚴(yán)謹(jǐn)代碼導(dǎo)致的,異常也暴漏在業(yè)務(wù)層代碼。

PROCESS_KILL類型

SWAP_FULL: 系統(tǒng)交換分區(qū)空間不足,系統(tǒng)清理;
LowMemoryKill:系統(tǒng)整機(jī)可用內(nèi)存較低,系統(tǒng)清理;
CAMERA_QUICK_Kll:相機(jī)場景內(nèi)存需求較大,需要查殺應(yīng)用清理內(nèi)存;
這個不是異常,如果想規(guī)避可以通過降低自身內(nèi)存占用,降低被清理的優(yōu)先級。

APP_FREEZE類型

主要對應(yīng)Appfreeze事件:
THREAD_BLOCK_6S 應(yīng)用主線程卡死超時。
APP_INPUT_BLOCK 用戶輸入響應(yīng)超時。
LIFECYCLE_TIMEOUT Ability生命周期切換超時。

主線程Watchdog(3S/6S)


image.png

用戶輸入事件超時5S


image.png

生命周期切換超時分為Ability生命周期切換超時和PageAbility生命周期切換超時。

該故障出現(xiàn)在生命周期切換的過程中,影響當(dāng)前應(yīng)用內(nèi)Ability的切換或者不同PageAbility之間的切換。

image.png

OOM類型

內(nèi)存溢出(Out Of Memory,簡稱OOM)是指應(yīng)用系統(tǒng)中存在無法回收的內(nèi)存或使用的內(nèi)存過多,最終使得程序運行要用到的內(nèi)存大于能提供的最大內(nèi)存。此時程序就運行不了,系統(tǒng)會提示內(nèi)存溢出。

RESOURCE_LEAK

資源泄漏是指句柄/線程/內(nèi)存等資源超過系統(tǒng)設(shè)定上限,部分資源甚至失去了管控能力,此時系統(tǒng)可能出現(xiàn)卡死/重啟等異常情況。LeakDetector模塊提供資源泄漏檢測、判決、維測日志抓取、日志上報的能力,為開發(fā)者提供詳細(xì)的維測日志以輔助故障定位。

image.png

故障恢復(fù)

代碼定位

TypeError類問題在實際應(yīng)用開發(fā)調(diào)試運行過程中是最常見的JS Crash類型,其表示為變量不是預(yù)期類型,在代碼層面則為對變量的使用未進(jìn)行事先的校驗,在錯誤日志中報錯多表現(xiàn)為如下:

Error name:TypeError
Error message:Cannot read property xxx of undefined

通過Error message很清除可以明白報錯原因。

JS調(diào)用棧可直接通過超鏈接跳轉(zhuǎn)到對應(yīng)錯誤代碼行,棧頂即為問題第一現(xiàn)場,如下樣例所示。

Device info:xxx
Build info:xxx-xxx x.x.x.xxx(xxxx)
Fingerprint:ed1811f3f5ae13c7262b51aab73ddd01df95b2c64466a204e0d70e6461cf1697
Module name:com.xxx.xxx
Version:1.0.0
VersionCode:1000000
PreInstalled:No
Foreground:Yes
Pid:31255
Uid:20020145
Reason:Error
Error name:Error
Error message:JSERROR
Sourcecode:
                throw new ErrOr("JSERROR");
                      ^
Stacktrace:
    at anonymous (entry/src/main/ets/pages/Index.ets:13:19)

異常代碼調(diào)用棧包含 SourceMap is not initialized yet ,表示因SourceMap轉(zhuǎn)換非常耗時,改為通過異步線程去進(jìn)行初始化,導(dǎo)致會出現(xiàn)SourceMap沒初始化完成就有異常產(chǎn)生的情況。針對這種情況增加這行日志來提示開發(fā)者。eTS棧對應(yīng)編譯后產(chǎn)物中代碼行號,可通過超鏈接跳轉(zhuǎn)到對應(yīng)錯誤代碼行。

Generated by HiviewDFX@HarmonyOS
================================================================
Device info:xxxx
Build info:xxxx
Fingerprint:9851196f9fed7fd818170303296ae7a5767c9ab11f38fd8b0072f0e32c42ea39
Module name:com.xxx.xxx
Version:1.0.0.29
VersionCode:10000029
PreInstalled:Yes
Foreground:No
Pid:2780
Uid:20020018
Reason:TypeError
Error name:TypeError
Error message:Cannot read property needRenderTranslate of undefined
Stacktrace:
Cannot get SourceMap info, dump raw stack:
    at updateGestureValue (phone/src/main/ets/SceneBoard/recent/scenepanel/recentpanel/RecentGesture.ts:51:51)
    at onRecentGestureActionBegin (phone/src/main/ets/SceneBoard/scenemanager/SCBScenePanel.ts:5609:5609)
    at anonymous (phone/src/main/ets/SceneBoard/scenemanager/SCBScenePanel.ts:555:555)
    at anonymous (phone/src/main/ets/SceneBoard/recent/RecentEventView.ts:183:183)

Cannot get SourceMap info, dump raw stack 信息表示該應(yīng)用為release包安裝,JS棧轉(zhuǎn)換eTS行列號失敗,可考慮使用應(yīng)用堆棧解析來解析行號。

應(yīng)用堆棧解析

將報錯信息直接使用ide查看,選擇DevEco Studio底部log選擇AnalyzeStackTrace,選擇Source map、So、Name cache,點擊start,右側(cè)就會把ts對應(yīng)的ets代碼映射關(guān)系出來。

image.png

或者使用三方網(wǎng)站 https://www.murzwin.com/base64vlq.html,將BaseEncode的報錯,decode解析出來,效果是這樣的,把ts的行列信息映射到ets中。

image.png

sourceMaps和nameCache分別在下面的勾對號和紅框里面的,文件是一樣的,可能是針對不同使用方使用的。所以在打APP包產(chǎn)物的時候要備份sourceMaps和nameCache文件,就是為了轉(zhuǎn)換報錯信息使用的。sourceMaps是解決行列信息,nameCache主要是為了解混淆文件使用的。

image.png

總結(jié)

通過上面我們很清楚的知道鴻蒙中故障分類和產(chǎn)生的原因、以及產(chǎn)生故障的代碼應(yīng)用層位置,我們就可以很容易去解決以上問題,從而降低線上的崩潰率。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容