我们知道,支撑页面在 webview 上良好运转的前提是具备一个高效并且稳定的 webview 容器,而容器的高效稳定不仅仅由容器提供方来保障,也需要容器使用者遵守一些基本准则,否则就有可能出现页面 Crash 的情况,这些准则是什么?什么样的上层代码会引起容器异常退出?这是本文需要阐述的内容。
H5 Crash 问题概况
下图是 H5 Crash 的大致流程图:
由于前端没办法捕捉到页面 Crash 的状态和堆栈,但是 H5 页面上发生的错误会传递到 Java 和更底层的 Native 直到容器异常退出,在退出的那一刻,容器会将堆栈写入到日志中,当下次打开容器时(也可能是定时上报)就会上报这些堆栈信息。
H5 Crash 原因初探
测试代码 仓库地址 :
git clone https://github.com/barretlee/h5crash.git;cd demo;
注意:代码需要在 Webview 容器中测试,PC 浏览器下不会出现异常。
H5 Crash 的原因不太明显,但是从经验上判断和摸索,大致归类为以下三种:
1. 内存问题
- 测试方法:使用闭包,不断增加内存量,看看增加到哪个区间大小, webview 容器会出现异常
- 测试地址: https://rawgit.com/barretlee/h5crash/master/demo/crash-memory.html (微信、微博或者其他客户端打开该页面的用户,可以点进去测试下,选择 100M 内存,不出意外,你的客户端会闪退。)
<script>var Closure = function() { var _cache = []; var cache = 0; var add = function(size) { cache += size; size = size * 1024 * 1024; _cache.push(new Array(size).join('x')); refresh(); }; var refresh = function() { r.innerHTML = '内存消耗: ' + cache + 'M'; }; return { cache: _cache + 'M', add: add, refresh: refresh }};var closure = Closure();</script><button onclick="closure.add(1)">增加 1M 内存消耗</button><button onclick="closure.add(10)">增加 10M 内存消耗</button><button onclick="closure.add(20)">增加 20M 内存消耗</button><button onclick="closure.add(50)">增加 50M 内存消耗</button><button onclick="closure.add(100)">增加 100M 内存消耗</button><div id="r">内存消耗:0 M</div>
- 存在的干扰:这种测试存在比较多的干扰,比如设备类型、系统类型(iOS/Android)、和设备内存运行状态等。
2. Layers 数问题
Layers 数的获取比较麻烦,Chrome Driver 没有提供该数据的接口,目前也没有比较好的办法拿到这个数据。
- 测试方法:通过不同的方式创建层,观察页面的 Crash 情况
- 测试地址: https://rawgit.com/barretlee/h5crash/master/demo/crash-layer.html
<style>.transform { transform: translateZ(0);}.animation { width:100px; height:100px; background:red; position:relative; animation:move 5s infinite;}@keyframes move { from {left:0px;} to {left:200px;}}</style><script>var Layer = function() { function getType() { return document.querySelector('input:checked').value; }; return { createOne: function(index) { var div = document.createElement('div'); div.appendChild(document.createTextNode(index)); switch(getType()) { case 'opacity': div.style.cssText = "opacity:" + (index / 1000); break; case 'transform': div.className = 'transform'; break; case 'animation': div.className = 'animation'; break; case 'zindex': div.style.cssText = "position:relative; z-index:" + index; break; } document.body.appendChild(div); }, create: function(num) { [].slice.call(document.querySelectorAll('div')).forEach(function(item) { item.parentNode && item.parentNode.removeChild(item); }); while(num--) { this.createOne(num); } } }};var layer = Layer();</script><strong>层类型: </strong><ul> <li><label><input type="radio" checked name="type" value="opacity"> <span>通过 opacity 创建层</span></label></li> <li><label><input type="radio" name="type" value="transform"> <span>通过 transforms 创建层</span></label></li> <li><label><input type="radio" name="type" value="animation"> <span>通过 animation 创建层</span></label></li> <li><label><input type="radio" name="type" value="zindex"> <span>通过绝对定位分层</span></label></li></ul><button onclick="layer.create(1)">创建 1 个层</button><button onclick="layer.create(10)">创建 10 个层</button><button onclick="layer.create(20)">创建 20 个层</button><button onclick="layer.create(50)">创建 50 个层</button><button onclick="layer.create(100)">创建 100 个层</button><button onclick="layer.create(200)">创建 200 个层</button><button onclick="layer.create(500)">创建 500 个层</button><button onclick="layer.create(1000)">创建 1000 个层</button><button onclick="layer.create(2000)">创建 2000 个层</button><button onclick="layer.create(5000)">创建 5000 个层</button><button onclick="layer.create(10000)">创建 10000 个层</button>
- 实际上,创建多个层,也是对内存的巨大消耗,页面 Crash 可能还是因为内存消耗过大
3. 并发过多问题
- 测试方法:尝试并发发出多种不同的请求(Fetch请求、XHR 请求、Script/CSS 资源请求),观察页面 Crash 情况
- 测试地址: https://rawgit.com/barretlee/h5crash/master/demo/crash-request.html
<script>var Request = function() { function getType() { return document.querySelector('input:checked').value; }; function getResource() { var type = getType(); var resource = { fetch: '/', xhr: '/', script: '//g.alicdn.com/sd/data_sufei/1.5.1/aplus/index.js', css: '//g.alicdn.com/kg/global-util/1.0.3/index-min.css' }; return resource[type]; }; return { emitOne: function() { var url = getResource() + "?_t=" + (new Date * 1 + Math.random()); switch(getType()) { case 'fetch': return fetch('/'); case 'xhr': with(new XMLHttpRequest) { open('GET', url); send(); } return; case 'script': var s = document.createElement('script'); s.src = url; document.body.appendChild(s); return; case 'css': var s = document.createElement('link'); s.href = url; document.body.appendChild(s); } }, emit: function(num) { [].slice.call(document.querySelectorAll('script,link')).forEach(function(item) { item.parentNode && item.parentNode.removeChild(item); }); while(num--) { this.emitOne(); } } }};var request = Request();</script><strong>请求类型: </strong><ul> <li><label><input type="radio" checked name="type" value="fetch"> <span>使用 Fetch 发送请求</span></label></li> <li><label><input type="radio" name="type" value="xhr"> <span>使用 XHR 发送请求</span></label></li> <li><label><input type="radio" name="type" value="script"> <span>并发请求脚本资源</span></label></li> <li><label><input type="radio" name="type" value="css"> <span>并发请求样式资源</span></label></li></ul><button onclick="request.emit(1)">并发 1 个请求</button><button onclick="request.emit(10)">并发 10 个请求</button><button onclick="request.emit(20)">并发 20 个请求</button><button onclick="request.emit(50)">并发 50 个请求</button><button onclick="request.emit(100)">并发 100 个请求</button><button onclick="request.emit(500)">并发 500 个请求</button><button onclick="request.emit(1000)">并发 1000 个请求</button>
- 存在的干扰:设备的种类、设备的 CPU 使用情况和网络状况等。
H5 Crash 测试结果
测试结果:
- 通过 opacity、animation、positon 等方式创建层,即便是 1w 个,页面也没有明显变化;但是使用 transform 创建 2k~5k 个层,页面会卡顿几秒后立即闪退;
- 内存是条红线,测试发现,一次性消耗 20M 的内存,会导致客户端立即闪退;
- 并发请求也是存在响应问题的,Fetch API 和 CSS Resource 并发 1k 请求没有出现问题,但是 XHR 和 Script Resource 请求,问题特别明显,虽然没有导致页面闪退,但是页面已经进入了假死状态。
以上临界值还可以继续精确。
小结
本文主要是对 H5 Crash 做了一个预研,测试可能存在诸多误差,测试方法也需要改进,不过沿着这些的思路考究会比较容易找到结论。
后续会给出比较有意义的边界数据以及探测工具。

WebDevelopmentReliesonHtml, CSS 및 JavaScript : 1) HtmlStructuresContent, 2) CSSSTYLESIT, 및 3) JAVASCRIPTADDSINGINTERACTIVITY, BASISOFMODERNWEBEXPERIENCES를 형성합니다.

HTML의 역할은 태그 및 속성을 통해 웹 페이지의 구조와 내용을 정의하는 것입니다. 1. HTML은 읽기 쉽고 이해하기 쉽게하는 태그를 통해 컨텐츠를 구성합니다. 2. 접근성 및 SEO와 같은 시맨틱 태그 등을 사용하십시오. 3. HTML 코드를 최적화하면 웹 페이지로드 속도 및 사용자 경험이 향상 될 수 있습니다.

"Code"는 "Code"BroadlyIncludeLugageslikeJavaScriptandPyThonforFunctureS (htMlisAspecificTypeofCodeFocudecturecturingWebContent)

HTML, CSS 및 JavaScript는 웹 개발의 세 가지 기둥입니다. 1. HTML은 웹 페이지 구조를 정의하고 등과 같은 태그를 사용합니다. 2. CSS는 색상, 글꼴 크기 등과 같은 선택기 및 속성을 사용하여 웹 페이지 스타일을 제어합니다.

HTML은 웹 구조를 정의하고 CSS는 스타일과 레이아웃을 담당하며 JavaScript는 동적 상호 작용을 제공합니다. 세 사람은 웹 개발에서 의무를 수행하고 화려한 웹 사이트를 공동으로 구축합니다.

HTML은 간단하고 배우기 쉽고 결과를 빠르게 볼 수 있기 때문에 초보자에게 적합합니다. 1) HTML의 학습 곡선은 매끄럽고 시작하기 쉽습니다. 2) 기본 태그를 마스터하여 웹 페이지를 만들기 시작하십시오. 3) 유연성이 높고 CSS 및 JavaScript와 함께 사용할 수 있습니다. 4) 풍부한 학습 리소스와 현대 도구는 학습 과정을 지원합니다.

anexampleStartingtaginhtmlis, whithbeginsaparagraph.startingtagsareessentialinhtmlastheyinitiate rements, definetheirtypes, andarecrucialforstructurituringwebpages 및 smanstlingthedom.

메뉴에서 점선 분할 효과를 설계하는 방법은 무엇입니까? 메뉴를 설계 할 때는 일반적으로 접시 이름과 가격 사이에 왼쪽과 오른쪽을 정렬하는 것이 어렵지 않지만 점선 또는 중간의 점은 어떻습니까?


핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

ZendStudio 13.5.1 맥
강력한 PHP 통합 개발 환경

Atom Editor Mac 버전 다운로드
가장 인기 있는 오픈 소스 편집기

드림위버 CS6
시각적 웹 개발 도구

MinGW - Windows용 미니멀리스트 GNU
이 프로젝트는 osdn.net/projects/mingw로 마이그레이션되는 중입니다. 계속해서 그곳에서 우리를 팔로우할 수 있습니다. MinGW: GCC(GNU Compiler Collection)의 기본 Windows 포트로, 기본 Windows 애플리케이션을 구축하기 위한 무료 배포 가능 가져오기 라이브러리 및 헤더 파일로 C99 기능을 지원하는 MSVC 런타임에 대한 확장이 포함되어 있습니다. 모든 MinGW 소프트웨어는 64비트 Windows 플랫폼에서 실행될 수 있습니다.

맨티스BT
Mantis는 제품 결함 추적을 돕기 위해 설계된 배포하기 쉬운 웹 기반 결함 추적 도구입니다. PHP, MySQL 및 웹 서버가 필요합니다. 데모 및 호스팅 서비스를 확인해 보세요.
