文档管理中心

App Killed(应用终止)检测

简介

应用闪退指应用在使用过程中突然异常终止。当应用行为异常,比如消耗过多CPU、内存等系统资源时,系统为了保持整机健康状态,会按照规则挑选应用进行管控,通常通过服务进程向应用发送SIGKILL信号(信号值是9)来实施终止的。操作系统对SIGKILL的默认行为是不生成栈日志等维测信息的,导致应用闪退时faultlogger中无日志。

基本概念

应用退出通常包含以下几种情况:

  1. 应用自身发生异常或主动抛出异常,例如因SIGSEGV、SIGABRT触发的CPP_CRASH异常,系统可监控并记录维测日志。

  2. 用户主动终止应用,例如在任务列表中点击清理按钮以清除所有应用,或上划清除单个应用,不会生成栈等维测日志。

  3. 应用开发者主动调用exit系统调用时,不会生成栈等维测日志。

  4. 应用发生主线程堵塞,导致界面冻结,通常会生成APP_FREEZE日志。

  5. 资源使用过度将导致系统对应用进行管控,并提供详细的维测信息。例如,应用发生内存泄漏时,通常会生成资源泄漏类的维测日志。开发者可以通过HiAppEvent订阅RESOURCE_OVERLIMIT获取对应的事件和日志。

  6. 系统对应用进行管控时,部分场景无法提供详细的维测信息,比如LowMemoryKiller、应用的RSS内存超过4GB、快速泄漏等。

本节主要覆盖在场景5和6中因SIGKILL信号导致的应用终止。

实现原理

  1. 内核和服务进程都会监控系统资源。

  2. 发现异常后,选择应用进行管控。

  3. 系统触发管控,终止应用时会添加系统事件打点。

  4. 打点事件中包含uid、包名、前后台信息、终止原因和维测信息。

约束和限制

  1. 应用需先通过HiAppEvent订阅,才能接收终止事件。

  2. 终止事件以异步的方式传递给应用,应用需在下次启动时才能接收到。

  3. 系统的管控行为会随着版本演进而不断新增,不保证当前的管控机制是系统的全部。

触发场景

系统终止应用,有以下的场景:

  1. 应用的内存、CPU和IO类负载超过一定限额,文件句柄和线程数量超标。

  2. 整机低内存时,会根据内存使用情况和优先级终止应用。

  3. 功耗类检查,包括应用Binder调用导致频繁唤醒、音频播放或录音导致系统无法冻结、GPS或蓝牙等外设使用异常问题。

感知方式

应用可以通过两种方式感知到被异常终止。

  1. 从元能力的Ability的onCreate回调参数中获取终止原因。具体为LaunchParam启动参数中的LastExitReason字段,请参考元能力LastExitReason章节

  2. 通过HiAppEvent订阅APP_KILLED事件。订阅方式请参考应用终止事件

分析思路和分析步骤

  1. 从Ability的onCreate回调参数中获取终止原因。

    可以参考下表进行处理。

    展开
    lastExitReason(enum) lastExitMessage(string) 产生原因 处理策略
    APP_FREEZE APP_FREEZE 由于watchdog检测出应用Freeze故障,导致应用程序退出。 通过HiAppEvent订阅APP_FREEZE事件,到APP_FREEZE事件中去匹配。
    RESOURCE_CONTROL CPU Highload CPU高负载。 尝试降低应用自身的CPU负载。
    RESOURCE_CONTROL CPU_EXT Highload 快速CPU负载检测。 尝试降低应用自身的CPU负载。
    RESOURCE_CONTROL IO Manager Control I/O管控。 尝试降低应用自身的I/O。
    RESOURCE_CONTROL App Memory Deterioration 应用内存超限劣化。 尝试通过HiAppEvent订阅RESOURCE_OVERLIMIT获取更多日志。
    RESOURCE_CONTROL Temperature Control 温度管控。 尝试降低应用自身的CPU负载。
    RESOURCE_CONTROL Memory Pressure 整机低内存触发,按优先级由低到高终止应用。 尝试降低应用自身的内存占用,以减少被整机管控策略选中的概率。
  2. 通过HiAppEvent订阅APP_KILLED事件。

    通过APP_KILLED事件,可以获取终止原因、应用前后台等关键信息,对照下表进行处理:

    展开
    reason(string) 产生原因 处理策略 是否应用自身异常触发管控 是否有关联事件
    LowMemoryKill 同前面的lastExitMessage值为Memory Pressure场景,即整机低内存触发,优先级由低到高终止应用。 尝试降低应用自身的内存占用,以减少被整机终止策略选中的概率。
    SwapFull Swap交换空间接近占满,可能存在个别进程内存泄漏,或者是后台进程个数太多。 尝试降低应用自身的内存占用,以减少被整机管控策略选中的概率。
    ResourceLeak(IonLeak) 应用占用的ION内存超标。 尝试通过HiAppEvent订阅RESOURCE_OVERLIMIT获取更多的ION内存日志,找到泄漏点后,降低应用自身的ION内存占用,一般来说是Image组件或者Pixmap泄漏导致。
    ResourceLeak(GpuRsLeak) 应用的ArkUI组件在render_service服务进程占用的GPU内存超标。 尝试降低应用ArkUI组件的GPU内存占用。
    ResourceLeak(GpuLeak) 应用在本进程内占用的GPU内存(即自渲染产生的GPU内存)超标。 尝试通过HiAppEvent订阅RESOURCE_OVERLIMIT获取更多的GPU内存日志,找到泄漏点后,降低应用自渲染(使用XComponent组件)的GPU内存占用。
    ResourceLeak(AshmemLeak) 应用占用的ashmem内存超标。 尝试通过HiAppEvent订阅RESOURCE_OVERLIMIT获取更多的ashmem内存日志,找到泄漏点后,降低应用自身的ashmem内存占用,一般来说是Image组件或者Pixmap泄漏导致。
    ResourceLeak(CES) CES注册超限。 尝试降低应用CES注册数量。
    ResourceLeak(PSSSoftLeak) 后台应用内存占用超过检测阈值两倍,其中pss内存占比最高。 尝试降低应用自身的内存占用。
    ResourceLeak(PSSLeak) 后台应用内存占用超过特定阈值,其中pss内存占比最高。 尝试降低应用自身的内存占用。
    ResourceLeak(VMALeak) VMA泄漏。 尝试降低应用自身的VMA内存占用,每次调用后释放对应虚拟内存区域。
    ResourceLeak(FDLeak) FD泄漏。 尝试通过HiAppEvent订阅RESOURCE_OVERLIMIT获取更多的FD泄漏日志,找到泄漏点后,及时关闭不必要的文件句柄。
    ResourceLeak(ThreadLeak) 线程泄漏。 尝试通过HiAppEvent订阅RESOURCE_OVERLIMIT获取更多的线程泄漏日志,找到泄漏点后,及时销毁不必要的线程。
    ResourceLeak(KernelZoneLeak) 页表内存泄漏。 无需处理。
    IllegalAudioRendererBySuspend 应用的音频播放未申请合理的后台任务,其退至后台后仍有大量音频播放。 应用退至后台时,应避免不必要的后台音频播放,或者合理使用后台任务,具体参考后台任务开发服务
    PowerSaveClean 整机切换到省电模式或应急模式。 无需处理。
    VrsKill 三方应用检测到恶意进程后,调用PC端病毒检测处置服务接口终止进程。 无需处理。
    RssThresholdKiller 应用的RSS内存超一定阈值。 尝试通过HiAppEvent订阅RESOURCE_OVERLIMIT获取更多的RSS内存日志,找到泄漏点后,尝试降低应用自身的内存占用,避免出现RSS内存超过阈值的情况。
    OomKiller 整机低内存,触发了内核管控,按照一定策略终止应用。 尝试降低应用自身的内存占用,以减少被整机管控策略选中的概率。
    CpaKiller DRM(Digital Rights Management)业务申请内存但是内存不足时,会按照一定策略终止进程以回收内存。 尝试降低应用自身的内存占用,以减少被整机管控策略选中的概率。
    KillApplication 应用主动退出。 无需处理。
    OnRemoteDied 远程服务死亡。 检查依赖的远程服务是否正常。
    Restart 应用重启。 无需处理。
    UserRequest 最近任务上划或清理。 无需处理。
    Uninstall 应用卸载退出。 无需处理。
    Upgrade 应用更新退出。 无需处理。
    Logout 用户注销时,卸载应用沙箱。 无需处理。
    PermissionUpdate 应用权限更新。 检查应用权限使用是否合理。
    aaForceStop 通过aa命令强制停止应用。 无需处理。
    ThreadBlock6S 应用主线程卡死超时。 检查应用主线程是否存在阻塞操作,优化代码逻辑。 是,具体参考ThreadBlock6S
    AppInputBlock 用户输入响应超时。 检查应用UI响应是否及时,优化输入处理逻辑。 是,具体参考AppInputBlock
    LifecycleTimeout 应用生命周期超时。 检查应用生命周期回调是否存在耗时操作。
    JsError js层程序崩溃。 检查js代码是否存在异常,优化错误处理。 是,具体参考JsError
    CppCrash native层程序崩溃。 检查native代码是否存在异常,优化错误处理。 是,具体参考CppCrash
    RSPixelMapFdOverLimit 应用使用图片PixelMap资源超限导致渲染服务fd泄漏。 尝试降低应用使用图片pixelMap资源的频率。
    CPUHighloadNotify 应用后台CPU高负载,出现弹框,用户选择停止该应用。 尝试降低应用自身的CPU负载。
    CPUHighloadUserRequest 应用后台CPU高负载,设置界面用户选择停止该应用。 尝试降低应用自身的CPU负载。
    IllegalAudioCapturerBySuspend 应用录音未申请合理的后台任务,其退至后台后仍进行录音。 应用退至后台时,应避免不必要的后台录音,或者合理使用后台任务。
    IOHighload IO高负载。 尝试降低应用自身的I/O操作。
    AppFreeze 应用冻屏无响应。 通过HiAppEvent订阅APP_FREEZE事件,到APP_FREEZE事件中去匹配。 是,具体参考AppFreeze
    MaliciousContinuousTaskActive 恶意连续任务活跃。 检查应用是否存在恶意连续任务,优化任务调度。
    RsDataOverflow RS数据溢出。 尝试降低应用RS数据使用量。
    HighTemperature 温度超限。 尝试降低应用自身的CPU负载,减少发热。
    TransientTaskTimeout 短时任务超时6s并且处于后台。 检查短时任务是否存在耗时操作,优化任务执行效率。
    TooManyReadyThreads 单进程就绪线程过多。 尝试减少应用创建的线程数量,优化线程管理。
    JsHeapSleepCleanKill sleep状态(夜间充电)进行js heapsize检测,超限后终止应用。 归类为整机后台内存清理,尝试优化js heap的使用率。
    HardwareDecodingResourcesLimit 硬件解码资源限制。 尝试减少应用对硬件解码资源的使用。
    AppRecoveryNotifyAppOverLimit 应用恢复通知应用超限。 检查应用恢复机制是否存在异常,优化恢复逻辑。
    GpuError GPU错误。 检查应用GPU使用是否合理,优化GPU资源管理。
    NotAttachedToStatusBar 未附加到状态栏。 检查应用状态栏附件逻辑是否正确。
    CPUHighload 应用后台CPU高负载,系统自动终止应用。 尝试降低应用自身的CPU负载。
    AshmemKiller 整机低内存,单进程ASHMEM内存超限。 尝试降低应用自身的ashmem内存占用。尝试通过HiAppEvent订阅RESOURCE_OVERLIMIT获取更多的ashmem内存超限日志。
    GpuKiller 整机低内存,单进程GPU占用达到阈值。 尝试降低应用自身的GPU内存占用。尝试通过HiAppEvent订阅RESOURCE_OVERLIMIT获取更多的单进程GPU占用达到阈值日志。
    DmaKiller 整机低内存,单进程Dma占用达到阈值。 尝试降低应用自身的Dma内存占用。尝试通过HiAppEvent订阅RESOURCE_OVERLIMIT获取更多的Dma占用达到阈值日志。
    ThreadKiller 单进程线程超限。 尝试减少应用创建的线程数量,优化线程管理。
    UninstallStorage 卸载存储卡。 无需处理。
搜索
请输入您想要搜索的关键词