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

标签 javascript android webview infinite-loop terminate

如果执行的 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 上调用销毁:webView.destroy();
  • 结束 Activity :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 代码创建您自己的多进程浏览器,但这可能需要更多的努力。

关于javascript - 如果执行的 JavaScript 进入无限循环,Android WebView 将进入不可恢复状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20681876/

相关文章:

javascript - 清除 Canvas 中的文本不允许我重画

android - PreferenceFragment 是否有意从兼容性包中排除?

javascript - 安卓 WebView : is there a way to get a javascript stack trace?

java - 带进度对话框的 webview android

android - 'onpageshow' 未在 Android WebView 应用程序上触发

javascript - 如何修复 Jquery 数据表中的第一个标题行和第一列

javascript - 检测午夜和重置数据的最佳方法

javascript - 在 AngularJs 中共享模块

java - android 中的影子生成器

android - Android中的圆圈语音动画