如果执行的 JavaScript 进入无限循环,Android WebView 将进入不可恢复状态

2024-01-29

如果执行的 JavaScript 代码陷入无限循环,Android WebView 小部件似乎会进入不可恢复的状态。

例如这个网页就会导致这个问题:

<html>
<head>
<title>FAIL</title>
<script type="text/javascript">
    function test() {
        while (true);
    }
</script>
</head>
<body onload="test();">
Failure Test
</body>

只需使用 WebView 在任何 Android 浏览器中输入以下 URL:

javascript:while(true);

一旦遇到这样的死循环,一个CPU核心就会最大限度地运行。 WebView 似乎永远不会关闭。这当然会快速耗尽电池并降低设备速度。只有终止包含的应用程序似乎才能解决此问题。

以下似乎无效:

  • 禁用 JavaScript:webView.getSettings().setJavaScriptEnabled(false);
  • 停止页面加载:webView.stopLoading();
  • 暂停所有 JS 计时器:webView.pauseTimers();
  • 加载备用 URL:webView.loadUrl("about:blank");
  • 从小部件层次结构中删除 WebView:parent.removeView(browserView);
  • 在 WebView 上调用 destroy:webView.destroy();
  • 结束活动:activity.finish();
  • 从 WebChromeClient.onJsTimeout() 返回 false; (此方法在 API 17 中已弃用,并且似乎从未被调用)。

以下是有效的:

  • 终止虚拟机:System.exit(0); (这是一个永远不应该在 Android 上调用的方法。)

值得注意的是,原生 Android 浏览器(不是 Chrome)也存在这个问题。尽管 Chrome 没有这个问题,但在使用 Android 4.4 中附带的基于 Chromium 的 WebView 时,它似乎仍然会出现。

一旦一个 WebView 进入此状态,应用程序将无法将任何 URL 加载到任何其他 WebView 中。

如果有人对终止 WebView 有任何建议,我们将不胜感激。我无法控制加载到 WebView 中的内容,因为它用于通用浏览器。否则,我的默认解决方案将是尝试检测该情况并在遇到该情况时警告用户,提供强制终止应用程序以防止电池耗尽的选项。

谢谢您的任何想法!


我认为你对此无能为力。因为 WebView 是单个进程(这对于 4.4 WebView 也是如此)并且渲染器在应用程序的进程中运行,行为不当的网页可能会导致您的进程因分配大量内存而被 OOM 终止。

Chrome 不会遇到这个问题,因为它在一个可以终止的单独进程中运行渲染器。可以修改 WebView 以杀死正在执行 JavaScript 的线程,但这会导致内存泄漏(因为操作系统不会像在单独进程的情况下那样为您清理),就像我上面所说的- 这样做并不能真正保护您免受分配内存的恶意网页的侵害。

我认为你的解决方案是显示“页面没有响应。杀死应用程序?”向用户弹出是使用 WebView 可以做的最好的事情。另一种方法是基于 Chromium 代码创建您自己的多进程浏览器,但这可能需要付出更多的努力。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如果执行的 JavaScript 进入无限循环,Android WebView 将进入不可恢复状态 的相关文章