0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

【鸿蒙】webview内存泄漏问题的分析报告

王程 2024-03-02 15:12 次阅读

1 关键字

webview;内存泄漏

2 问题描述

问题现象:在 3.1release 版本和 3.2bete1 版本中,在 RK3568 上使用 etsWeb 和其他浏览器时,webview 所占的内存会随着使用而不断增大,最终导致浏览器 APP 因内存泄漏而崩溃。

3 问题原因

3.1 正常机制

在任意版本上使用浏览器 APP,可以长时间正常浏览网页。

3.2 异常机制

在 3.1release 和 3.2beta1 上使用浏览器 APP,长时间浏览网页后,应用会崩溃。

4 解决方案

  • arkui web 侧,在析构函数中调用 OnDestroy 方法销毁组件
    //文件路径
foundationarkuiace_engineframeworkscorecomponentswebresourceweb_delegate.cpp
WebDelegate::~WebDelegate()
{
    ReleasePlatformResource();
    if (nweb_) {
        nweb_->OnDestroy();
    }
}

  • web 内核中的 compositor 被 delete 的过程如下
//文件路径srcceflibcefbrowserosrrender_widget_host_view_osr.cc
#include "ui/gfx/geometry/size_conversions.h"
#include "ui/touch_selection/touch_selection_controller.h"
 
// static
std::unordered_map<  gfx::AcceleratedWidget, ui::Compositor*  >
    CefRenderWidgetHostViewOSR::compositor_map_;
 
std::unordered_map<  gfx::AcceleratedWidget, uint32_t  > CefRenderWidgetHostViewOSR::accelerate_widget_map_;
 
namespace {
// The maximum number of damage rects to cache for outstanding frame requests
// (for OnAcceleratedPaint).
const size_t kMaxDamageRects = 10;
  compositor_->SetRootLayer(root_layer_.get());
  compositor_->AddChildFrameSink(GetFrameSinkId());
#else
  LOG(INFO) <  < "compositor construct, widget = " <  < static_cast<  uint32_t  >(browser_impl_->GetAcceleratedWidget());
  ui::Compositor* compositor = CefRenderWidgetHostViewOSR::GetCompositor(
      browser_impl_->GetAcceleratedWidget());
  accelerate_widget_map_[browser_impl_->GetAcceleratedWidget()]++;
  if (!compositor) {
    compositor = new ui::Compositor(
        context_factory->AllocateFrameSinkId(), context_factory,
  if (!compositor_) {
    return;  // already released
  }
#else
  if (!browser_impl_) {
    return;
  }
  auto it = accelerate_widget_map_.find(browser_impl_->GetAcceleratedWidget());
  if (it == accelerate_widget_map_.end()) {
    return;
  }
#endif
  // Marking the DelegatedFrameHost as removed from the window hierarchy is
  // necessary to remove all connections to its old ui::Compositor.
 
  if (delegated_frame_host_) {
    if (is_showing_) {
      delegated_frame_host_->WasHidden(content::DelegatedFrameHost::HiddenCause::kOther);
    }
    delegated_frame_host_->DetachFromCompositor();
    delegated_frame_host_.reset(nullptr);
  }
 
#ifdef DISABLE_GPU
  compositor_.reset(nullptr);
#else
  LOG(INFO) <  < "ReleaseCompositor";
  if(--accelerate_widget_map_[browser_impl_-  >GetAcceleratedWidget()] == 0) {
    if (!browser_impl_) {
      return;
    }
    LOG(INFO) <  < "ReleaseCompositor, widget = " <  < static_cast<  uint32_t  >(browser_impl_->GetAcceleratedWidget());
    auto it = compositor_map_.find(browser_impl_->GetAcceleratedWidget());
    if (it != compositor_map_.end()) {
      if (it->second != nullptr) {
        delete it->second;
      }
      compositor_map_.erase(it);
    }
    accelerate_widget_map_.erase(browser_impl_->GetAcceleratedWidget());
  }
#endif
}

5 定位过程

在 RK3568 上使用 etsWeb 时,使用下列命令可以看到浏览器的进程号 pid 和进程所占内存情况。

ps -ef #查看pid
hidumper --mem 1021 #查看进程所占内存,这里的1021是进程号pid的示例,具体进程号请使用前面提到的命令查看

可以看出浏览器进程所占用的内存会随着网页数量增对而增加,进程在占用内存达到 300M 至 400M 时会崩溃。在增大 basewebwebviewbundle.json 中的 ram 值后,最大占用内存可达到 600M 至 700M,此时浏览器虽然不会崩溃,但是整机会变得非常卡,已经无法使用。研究过相关代码后发现,目前 webview 尚无自动回收资源的接口,这就导致浏览器的网页占用的资源得不到有效的释放,进而导致浏览器进程占用的内存不断增加,最终崩溃。

具体原因是:

1.web 组件销毁时,增加的内存无法被回收,arkui web 组件侧因为强指针相互引用,导致析构函数没有被调用。
2.web 内核侧的 OnDestory 接口没有被调用,内核侧资源没有被回收。
3.web 内核侧 GPU 渲染,new 出来的 compositor 没有被 delete。
经过研究,webview 的内存资源得不到释放的情况系版本 bug,并且这个问题在最新的 master 版本和 3.2beta2 版本已修复。

6 知识分享

1.使用智能指针 shared_ptr 时要注意不可以互相引用,否则会导致引用数量无法清零导致内存泄漏;
2.增大系统预设 ram 可以使某些占用内存大的 APP 使用情况得到改善,但从系统总体来看,这种方法存在后患,可能会引发意想不到的问题。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 内存泄漏
    +关注

    关注

    0

    文章

    39

    浏览量

    9205
  • webview
    +关注

    关注

    0

    文章

    7

    浏览量

    3128
  • 鸿蒙
    +关注

    关注

    57

    文章

    2307

    浏览量

    42737
  • HarmonyOS
    +关注

    关注

    79

    文章

    1967

    浏览量

    30012
收藏 人收藏

    评论

    相关推荐

    鸿蒙Flutter实战:04-如何使用DevTools调试Webview

    # 鸿蒙 Flutter 如何使用 DevTools 调试 Webview 在《鸿蒙 Flutter 开发中集成 Webview》,介绍了如果在 Flutter 中集成
    发表于 10-22 21:53

    AliOS Things 维测典型案例分析 —— 内存泄漏

    维测典型案例分析1 —— 内存泄漏在系统运行的过程中,内存泄漏是较为常见但是很难复现的现象,一般的内存
    发表于 10-17 11:29

    如何在鸿蒙webview上面放其它组件?

    需求:需要在鸿蒙webview上显示一个网页,在webview上面再添加一个文本,但是无论怎么webview都会覆盖掉其它组件,这个是鸿蒙
    发表于 03-28 10:00

    项目中webview需要传递token,请问鸿蒙webview里怎么传递请求头?

    鸿蒙webview怎么添加请求头token,类似于安卓的loadUrl(String var1, Map var2)
    发表于 03-29 10:26

    鸿蒙webview如何设置请求头?

    ;, DownloadType.HOST);mWebView.loadUrl(mUrl,webviewHead);请问下鸿蒙webview怎么设置请求头,文档上也没有找到诶
    发表于 05-11 11:29

    紧急!鸿蒙webview如何设置请求头

    紧急!鸿蒙webview如何设置请求头
    发表于 05-12 14:41

    鸿蒙webview加载不了网页是为什么?

    鸿蒙webview怎么使用呢 权限给了 就是加载不了网页
    发表于 06-09 09:54

    鸿蒙webview加载Vue h5失败是什么原因导致的?

    : ignored但该H5 url在Android webview能正常加载,且鸿蒙webview能正常加载https:百度、华为论坛等其他url,唯独加载这个vue h5 失败,求大佬指点
    发表于 06-09 10:05

    C++内存泄漏分析方法

    C++是一种非常流行的计算机编程语言,在使用的过程中容易出现内存泄漏问题,而该问题往往难以识别。给出了一种对C++内存泄漏问题进行分析的方法
    发表于 11-23 11:19 5次下载
    C++<b class='flag-5'>内存</b><b class='flag-5'>泄漏</b><b class='flag-5'>分析</b>方法

    鸿蒙webview的使用和JS交互

    日常我们在开发项目时,为了项目快速的开发和迭代,难免会用到H5页面。使用鸿蒙进行项目开发时,也一样免不了要加载H5页面,在移动开发中打开H5页面需要使用WebView组件。同时,为了和H5页面进行数据交换,有时候还需要借助JSBridge来实现客户端与H5之间的通讯。
    的头像 发表于 02-28 10:56 2498次阅读
    <b class='flag-5'>鸿蒙</b><b class='flag-5'>webview</b>的使用和JS交互

    什么是内存泄漏内存泄漏有哪些现象

    内存泄漏几乎是很难避免的,不管是老手还是新手,都存在这个问题,甚至 Windows 与 Linux 这类系统软件也或多或少存在着内存泄漏
    的头像 发表于 09-05 17:24 9609次阅读

    什么是内存泄漏?如何避免JavaScript内存泄漏

    JavaScript 代码中常见的内存泄漏的常见来源: 研究内存泄漏问题就相当于寻找符合垃圾回收机制的编程方式,有效避免对象引用的问题。
    发表于 10-27 11:30 361次阅读
    什么是<b class='flag-5'>内存</b><b class='flag-5'>泄漏</b>?如何避免JavaScript<b class='flag-5'>内存</b><b class='flag-5'>泄漏</b>

    线程内存泄漏问题的定位

    记录一个关于线程内存泄漏问题的定位过程,以及过程中的收获。 1. 初步定位 是否存在内存泄漏:想到内存
    的头像 发表于 11-13 11:38 582次阅读
    线程<b class='flag-5'>内存</b><b class='flag-5'>泄漏</b>问题的定位

    如何发现内存泄漏

    检测两个角度介绍在 Linux 环境进行内存泄漏检测的方法,并重点介绍静态分析工具 BEAM、动态监测工具 Valgrind 和 rational purify 的使用方法。相信通过本文的介绍,能给大家对处理其它产品或项目
    的头像 发表于 11-13 15:41 569次阅读

    C语言内存泄漏问题原理

    内存泄漏问题只有在使用堆内存的时候才会出现,栈内存不存在内存泄漏问题,因为栈
    发表于 03-19 11:38 482次阅读
    C语言<b class='flag-5'>内存</b><b class='flag-5'>泄漏</b>问题原理