鸿蒙5.0 APP性能优化实战——JS Crash问题排查方法

往期推文全新看点(文中附带全新鸿蒙5.0全栈学习笔录)

✏️ 鸿蒙应用开发与鸿蒙系统开发哪个更有前景?

✏️ 嵌入式开发适不适合做鸿蒙南向开发?看完这篇你就了解了~

✏️ 对于大前端开发来说,转鸿蒙开发究竟是福还是祸?

✏️ 鸿蒙岗位需求突增!移动端、PC端、IoT到底该怎么选?

✏️ 记录一场鸿蒙开发岗位面试经历~

✏️ 持续更新中……


当未处理的JS异常导致应用意外退出时,应用会在抛出未处理的异常时崩溃并且会生成对应的JS Crash崩溃日志文件。开发者可通过错误日志查看引起崩溃的代码位置及分析应用崩溃的原因。

本文将分别介绍JS Crash异常捕获场景,JS Crash故障分析思路。

JsCrash日志分析

JsCrash日志包含异常原因及异常堆栈等定位关键信息,以下是进程崩溃日志信息中对应字段解释。

Build info:XXX-XXXX X.X.X.XX(XXXXXXXX) <- 版本信息
Module name:com.example.myapplication <- 模块名
Version:1.0.0 <- 版本号
Pid:579 <- 进程号
Uid:0 <- 用户ID
Reason:TypeError <- 原因
Error message:Cannot read property c of undefined <- 异常信息
Cannot get SourceMap info, dump raw stack: <- 应用安装包为release包安装时不包含sourcemap文件,JS栈通过sourcemap行列号解析会失败
Stacktrace:
    at onPageShow (entry/src/main/ets/pages/Index.ets:7:13)  <-异常代码调用栈
           ^                                      ^
         函数名异常代码文件行列号位置

JS Crash多为应用问题,开发者可通过崩溃文件中的 Error message 和 StackTrace 来定位问题。

JS Crash异常捕获场景

JS Crash异常根据不同的异常场景,在 Reason 字段进行了分类,分为Error、TypeError、SyntaxError、RangeError等错误类型。

  • 自定义 Error 类:Error 是最基本的错误类型,其他的错误类型都继承自该类型。Error 对象主要有两个重要属性 message 和 name 分别表示错误信息和错误名称。程序运行过程中抛出的异常一般都有具体的类型,Error 类型一般都是开发人员自己抛出的异常。
  • TypeError(类型错误)类:运行时最常见的异常,表示变量或参数不是预期类型。
  • SyntaxError(语法错误)类:语法错误也称为解析错误。语法错误在任何编程语言中都是最常见的错误类型,表示不符合编程语言的语法规范。
  • RangeError(边界错误)类:表示超出有效范围时发生的异常,主要的有以下几种情况:
    • 数组长度为负数或超长
    • 数字类型的方法参数超出预定义范围
    • 函数堆栈调用超过最大值
  • ReferenceError —— 引用错误:引用一个不存在的变量时发生的错误,每当我们创建一个变量时,变量名称都会写入一个变量存储中心中,这个变量存储中心就像键值存储一样,每当我们引用变量时,它都去存储中找到 key并提取并返回 value,如果我们要找的变量不在存储中,就会抛出 ReferenceError。
  • URI Error —— URL错误:在调用 URI 相关的方法中 URL 无效时抛出的异常,主要包括 encodeURI()、decodeURI()、encodeURIComponent()、decodeURIComponent()、escape() 和 unescape() 几个函数 。

问题定位思路

获取日志

进程崩溃日志是一种故障日志,与应用无响应日志、JS应用崩溃等都由FaultLogger模块管理,可通过以下方式获取:

  • 方式一:通过DevEco Studio获取日志

    DevEco Studio会收集设备“/data/log/faultlog/faultlogger/”路径下的进程崩溃故障日志并归档在FaultLog下

  • 方式二:通过faultlogger接口获取

    faultlogger对外提供了故障查询接口,可以查询各种故障信息 。

  • 方式三:通过hiAppEvent接口订阅故障

    hiAppEvent 对外提供了故障订阅接口,可以订阅各类故障信息

  • 方式四:通过shell获取日志进程崩溃后,JS Crash文件会生成在设备“/data/log/faultlog/faultlogger/”路径下,故障日志文件名格式为“jscrash-进程名-进程UID-秒级时间”,包含设备名、系统版本、进程崩溃调用栈等信息。

根因分析

JS Crash问题分析一般根据上述异常的场景,结合错误信息、调用栈定位到源码,可得出基本的分析结论。对于调用栈的分析有以下几种情况。

StackTrace 场景分类

JS Crash故障日志中,StackTrace 字段存放的是 JS Crash 异常的调用栈信息,StackTrace 的显示分为以下几种场景。

  1. JS调用栈可直接通过超链接跳转到对应错误代码行,栈顶即为问题第一现场,如下样例所示。
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
Stacktrace:
    at anonymous (entry/src/main/ets/pages/Index.ets:13:19)
  1. 异常代码调用栈 Stack Cannot get SourceMap info, dump raw stack,表示因SourceMap转换失败,仅展示eTS栈对应编译后产物中代码行号,可通过超链接跳转到对应错误代码行,如下样例所示。
Device info:xxx
Build info:xxx-xxx x.x.x.xxx(xxxx)
Fingerprint:a370fceb59011d96e41e97bda139b1851c911012ab8c386d1a2d63986d6d226d
Module name:com.xxx.xxx
Version:1.0.0
Versioncode:1000000
PreInstalled:No
Foreground:Yes
Pid:39185
Uid:20020145
Reason:Error
Error name:Error
Error message:JSERROR
Stacktrace:
Cannot get SourceMap info, dump raw stack:
    at anonymous (entry/src/main/ets/pages/Index.ts:49:49)
  1. 异常代码调用栈包含 SourceMap is not initialized yet ,表示因SourceMap转换非常耗时,改为通过异步线程去进行初始化,导致会出现SourceMap没初始化完成就有异常产生的情况。针对这种情况增加这行日志来提示开发者。eTS栈对应编译后产物中代码行号,可通过超链接跳转到对应错误代码行。如下样例所示。
Device info:xxx
Build info:xxx-xxx x.x.x.xxx(xxxx)
Fingerprint:377ef8529301363f373ce837d0bf83aacfc46112502143237e2f4026e86a0510
Module name:com.xxx.xxx
Version:1.0.0
Versioncode:1000000
PreInstalled:No
Foreground:Yes
Pid:6042
Uid:20020145
Reason:Error
Error name:Error
Error message:JSERROR
Stacktrace:
SourceMap is not initialized yet
at anonymous (entry/src/main/ets/pages/Index.ts:49:49)
  1. 异常代码调用栈中打印native栈,栈顶一般为libark_jsruntime.so动态库,这是因为JS异常最后都会经过虚拟机抛出。从崩溃栈从上往下找,libace_napi.z.so的上一帧一般是抛出异常的现场。如下样例所示。
Device info:xxx
Build info:xxx-xxx x.x.x.xxx(xxxx)
Fingerprint:89f2b64b24d642b0fc64e3a7cf68ca39fecaa580ff5736bb9d6706ea4cdf2c93
Module name:com.xxx.xxx
Version:1.0.0
VersionCode:1000000
PreInstalled:No
Foreground:No
Pid:14325
Uid:20020145
Reason:ReferenceError
Error name:ReferenceError
Error message:Cannot find module 'com.xxx.xxx/entry/EntryAbility' , which is application Entry Point
Stacktrace:
SourceMap is not initialized yet
#01 pc 000000000028ba3b /system/libó4/platformsdk/libark_jsruntime.so(bf6ea8e474ac3e417991f101e062fa90)
#02 pc 00000000001452ff /system/libó4/platformsdk/libark_jsruntime.so(bf6ea8e474ac3e417991f101e062fa90)
#03 pC 0000000000144c9f /system/libó4/platformsdk/libark_jsruntime.so(bf6ea8e474ac3e417991f101e062fa90)
#04 pc 00000000001c617b /system/libó4/platformsdk/libark_jsruntime.so(bf6ea8e474ac3e417991f101e062fa90)
#05 pc 00000000004c3cb7 /system/libó4/platformsdk/libark_jsruntime.so(bf6ea8e474ac3e417991f101e062fa90)
#06 pc 00000000004c045f /system/libó4/platformsdk/libark_jsruntime.so(bf6ea8e474ac3e417991f101e062fa90)
#07 pc 000000000038034f /system/libó4/platformsdk/libark_jsruntime.so(bf6ea8e474ac3e417991f101e062fa90)
#08 pc 00000000004b2d9b /system/libó4/platformsdk/libark_jsruntime.so(bf6ea8e474ac3e417991f101e062fa90)
#09 pc 0000000000037e7f /system/libó4/platformsdk/libace_napi.z.so(10ceafd39b5354314d2fe3059b8f9e4f)
#10 pc 00000000000484cf /system/lib64/platformsdk/libruntime.z.so(3f6305a3843fae1de148a06eec4bd014) <- 异常抛出位置
#11 pc 000000000004fce7 /system/libó4/platformsdk/libruntime.z.so(3f6305a3843fae1de148a06eec4bd014)
#12 pc 000000000004e9fb /system/libó4/platformsdk/libruntime.z.so(3f6305a3843fae1de148a06eec4bd014)
#13 pc 000000000004eb7b /system/libó4/platformsdk/libruntime.z.so(3f6305a3843fae1de148a06eec4bd014)
#14 pc 000000000004f5c7 /system/libó4/platformsdk/libruntime.z.so(3f6305a3843fae1de148a06eec4bd014)
#15 pc 00000000000303cf /system/lib64/platformsdk/libuiabilitykit_native.z.so(3203F4CCe84a43b519d0a731dfOdb1a3)

调用栈分析

调用栈分析会有如下两种情况:

  • 情况一:可跳转至引起错误的代码行

    如果FaultLog的堆栈信息中的链接或偏移地址指向的是当前工程中的某行代码,该段信息将被转换为超链接形式,在DevEco Studio中点击后跳转至对应代码行。

  • 情况二:不可跳转至引起错误的代码行或者跳转代码位置不存在

    如出现Cannot get Source Map info, dump raw stack信息代表js栈转换ets行列号失败,在DevEco Studio中点击链接会跳转到不正确的代码位置或不存在的代码行位置。

异常定位信息增强工具说明

案例一:模块化相关异常

可使用DevEco Studio集成工具,选择以接收更详细的错误信息。此功能仅适用于从ArkTS调用C++代码时发生的错误。 勾选红框选项,如下样例所示。

需要删除镜像中/system/lib64/module/libhidebug.z.so中的文件,代码如下样例所示。

import { hidebug } from '@kit.PerformanceAnalysisKit';

@Entry
@Component
struct Index {
  @State message: string = 'Hello World';
  build() {
    RelativeContainer() {
      Text(this.message)
        .id('HelloWorld')
        .fontSize(50)
        .fontWeight(FontWeight.Bold)
        .alignRules({
          center: { anchor: '__container__', align: VerticalAlign.Center },
          middle: { anchor: '__container__', align: HorizontalAlign.Center }
        })
        .onClick(()=>{
            hidebug.getPss();
        })
    }
    .height('100%')
    .width('100%')
  }
}

未勾选Enhanced Error Info

勾选Enhanced Error Info

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值