应用导入大量图片后卡死
===========

#### 问题现象

应用在导入大量图片后，页面卡死无响应。

#### 背景知识

*   应用中的Web组件运行时，系统会为之分配一个Render进程，用于渲染。如图中的“Render Process”。参考文档[进程模型](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/process-model-stage)。![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/4e/v3/h9_AlIZHR6aXomgwEFgvPg/zh-cn_image_0000002658794245.png?HW-CC-KV=V1&HW-CC-Date=20260709T133736Z&HW-CC-Expire=86400&HW-CC-Sign=4E658CD5A622A21ABC76D825AEBAE3EE0B6B59D3D4785DE0A825B878DB4873D0 "点击放大")
*   WebView是多渲染进程的，当一个Web应用打开多个页面后，每个页面都有一个渲染进程。

#### 问题定位

1.  查看faultlogger目录，没有appfreeze日志，说明应用没有发生卡死。
2.  查看hilog日志，观察到chromium字段，说明界面采用的是Web组件，搜索关键字com.hx.example:render，可以看到应用渲染进程id是15400。
    
    06-23 15:01:15.076 15400 15400 W C04501/com.hx.example:render/chromium: \[nodict\]\[render\_frame\_impl.cc:4038\] event\_message: content load finished, routing\_id: 1, url: \*\*\*
    06-23 15:01:15.086 15400 15400 W C04501/com.hx.example:render/chromium: \[nodict\]\[render\_frame\_impl.cc:4081\] event\_message: page load finished, routing\_id: 1, url: \*\*\*
    06-23 15:01:15.404 15400 15400 I C04501/com.hx.example:render/chromium: \[nodict\]\[paint\_timing.cc:134\] event\_message: MarkFirstContentfulPaint
    06-23 15:01:15.527 15400 15400 I C04501/com.hx.example:render/chromium: \[nodict\]\[frame\_selection.cc:949\] Focused Or Active State Changed, focused=0, active\_and\_focused=0
    
3.  搜索关键字ProcMgr，可以看到应用渲染进程15400在15:06:13已经终止，和页面发生卡死的时间一致。
    
    06-23 15:06:13.095   850 26512 I C02699/memmgrservice/MemMgr: PrioManager::UpdatePriorityLocked pid=15400, bundleUid=20020161, bundleName=com.hx.example, procName=com.hx.example, time=1750662373087500000, reason=PROCESS\_TERMINATED
    06-23 15:06:13.095  1375  1447 I C05A02/privacy\_service/PermissionRecordManager: \[RemoveRecordFromStartListByPid:913\]TokenId 0, pid 15400
    06-23 15:06:13.095  1375  6430 I C05A02/privacy\_service/PrivacySecCompEnhanceAgent: \[OnProcessDied:37\]OnProcessDied pid 15400
    06-23 15:06:13.095  1375  6430 E C05A02/privacy\_service/PrivacySecCompEnhanceAgent: \[RemoveSecCompEnhance:112\]Not found pid 15400 data.
    06-23 15:06:13.096   850 26512 E C02699/memmgrservice/MemMgr: PrioManager::UpdatePriorityLocked reason=PROCESS\_TERMINATED, res: proc\[pid=15400\] is not exist
    06-23 15:06:13.096   789   789 I C01707/concurrent\_task\_service/CONCUR: \[ProcMgr\] process 15400 died
    
4.  搜索关键字EXIT\_REASON\_TAG，查看进程退出的原因，可以看到渲染进程退出的原因是应用内存超限（App Memory Deterioration）。
    
    06-23 15:06:13.113   652 26493 I C02DA0/hiview/FaultLeakDetectorManager: NotifyProcessDied: NotifyProcessDied process:com.hx.example:15400
    06-23 15:06:13.113  2412 25117 I C01560/wifi\_manager\_service/OHWIFI\_HANDLER: StaStateMachine ExecuteMessage msg:2
    06-23 15:06:13.115   652  2724 I C01336/hiview/AMS: \[ability\_manager\_client.cpp:1607\]\[EXIT\_REASON\_TAG\] pid:1, reason:7, exitMsg: App Memory Deterioration
    06-23 15:06:13.119  1510  2540 I C01336/foundation/AMS: \[ability\_manager\_service.cpp:2406\]\[EXIT\_REASON\_TAG\] pid:1, reason:7, exitMsg:App Memory Deterioration
    

#### 分析结论

应用内存超限导致渲染进程异常终止，从而使页面发生了卡死。

#### 修改建议

监听[onRenderExited](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/arkts-basic-components-web-events#onrenderexited9)事件来获取具体的退出原因[RenderExitReason](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/arkts-basic-components-web-e#renderexitreason9)，并在异常回调中根据退出的具体原因，执行相应的异常处理。

import { webview } from '@kit.ArkWeb';

@Entry
@Component
struct WebComponent {
  needReloadWhenVisible: boolean = false; _// Web组件不可见时render退出后阻止重新加载页面，在可见时重新加载页面。_
  webIsVisible: boolean = false; _// 判断Web组件是否可见。_
 _ // 此处是将子进程异常崩溃和其它异常原因做了区分，应用开发者可根据实际业务特点，细化对应异常的处理策略。_
  renderReloadMaxForCrashed: number = 5; _// 设置因为异常崩溃后重新加载的最大重试次数，应用可根据业务特点，自行设置试错上限。_
  renderReloadCountForCrashed: number = 0; _// 异常崩溃后重新加载的次数。_
  renderReloadMaxForOthers: number = 10; _// 设置因为其它异常原因退出的最大重试次数，应用可根据业务特点，自行设置试错上限。_
  renderReloadCountForOthers: number = 0; _// 其它异常原因退出后重新加载的次数。_
  _// 创建Web组件。_
  controller: webview.WebviewController = new webview.WebviewController();
  _// 指定加载的页面。_
  url: string = 'xx.xx.xx';

  build() {
    Column() {
      Web({ src: this.url, controller: this.controller })
        .fileAccess(false)
        .geolocationAccess(false)
        .onVisibleAreaChange(\[0, 1.0\], (isVisible) => {
          this.webIsVisible = isVisible;
          if (isVisible && this.needReloadWhenVisible) { _// Web组件可见时重新加载页面。_
            this.needReloadWhenVisible = false;
            this.controller.loadUrl(this.url);
          }
        })
       _ // 应用监听渲染子进程异常退出回调，并进行异常处理。_
        .onRenderExited((event) => {
          if (!event) {
            return;
          }
          if (event.renderExitReason == RenderExitReason.ProcessCrashed) {
            if (this.renderReloadCountForCrashed >= this.renderReloadMaxForCrashed) {
            _  // 设置重试次数上限保护，避免必现问题导致页面被循环加载。_
              return;
            }
            console.log('renderReloadCountForCrashed: ' + this.renderReloadCountForCrashed);
            this.renderReloadCountForCrashed++;
          } else {
            if (this.renderReloadCountForOthers >= this.renderReloadMaxForOthers) {
             _ // 设置重试次数上限保护，避免必现问题导致页面被循环加载。_
              return;
            }
            console.log('renderReloadCountForOthers: ' + this.renderReloadCountForOthers);
            this.renderReloadCountForOthers++;
          }
          if (this.webIsVisible) {
           _ // Web组件可见则立即重新加载。_
            this.controller.loadUrl(this.url);
            return;
          }
         _ // Web组件不可见时不立即重新加载。_
          this.needReloadWhenVisible = true;
        });
    };
  }
}