iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >Android如何解决WebView多进程崩溃的问题
  • 680
分享到

Android如何解决WebView多进程崩溃的问题

2023-06-14 07:06:52 680人浏览 泡泡鱼
摘要

小编给大家分享一下Android如何解决WEBView多进程崩溃的问题,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!问题在android 9.0系统上如果多个进程

小编给大家分享一下Android如何解决WEBView多进程崩溃的问题,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!

问题

在android 9.0系统上如果多个进程使用WebView需要使用官方提供的api在子进程中给webview的数据文件夹设置后缀:

WebView.setDataDirectorySuffix(suffix);

否则将会报出以下错误:

Using WebView from more than one process at once with the same data directory is not supported. https://crbug.com/5583771 com.android.webview.chromium.WebViewChromiumAwInit.startChromiumLocked(WebViewChromiumAwInit.java:63)2 com.android.webview.chromium.WebViewChromiumAwInitForP.startChromiumLocked(WebViewChromiumAwInitForP.java:3)3 com.android.webview.chromium.WebViewChromiumAwInit$3.run(WebViewChromiumAwInit.java:3)4 android.os.Handler.handleCallback(Handler.java:873)5 android.os.Handler.dispatchMessage(Handler.java:99)6 android.os.Looper.loop(Looper.java:220)7 android.app.ActivityThread.main(ActivityThread.java:7437)8 java.lang.reflect.Method.invoke(Native Method)9 com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:500)10 com.android.internal.os.ZyGoteInit.main(ZygoteInit.java:865)

通过使用官方提供的方法后问题只减少了一部分,从bugly后台依然能收到此问题的大量崩溃信息,以至于都冲上了崩溃问题Top3。

问题分析

源码分析调用链最终调用到了AwDataDirLock类中的lock方法。

public class WebViewChromiumAwInit { protected void startChromiumLocked() {   ...   AwBrowserProcess.start();   ...  }}public final class AwBrowserProcess { public static void start() {   ...   AwDataDirLock.lock(appContext);}

AwDataDirLock.java

abstract class AwDataDirLock { private static final String TAG = "AwDataDirLock"; private static final String EXCLUSIVE_LOCK_FILE = "webview_data.lock"; // This results in a maximum wait time of 1.5s private static final int LOCK_RETRIES = 16; private static final int LOCK_SLEEP_MS = 100; private static RandoMaccessFile sLockFile; private static FileLock sExclusiveFileLock; static void lock(final Context appContext) {  try (ScopedSysTraceEvent e1 = ScopedSysTraceEvent.scoped("AwDataDirLock.lock");    StrictModeContext ignored = StrictModeContext.allowDiskWrites()) {   if (sExclusiveFileLock != null) {    // We have already called lock() and successfully acquired the lock in this process.    // This shouldn't happen, but is likely to be the result of an app catching an    // exception thrown during initialization and discarding it, causing us to later    // attempt to initialize WebView again. There's no real advantage to failing the    // locking code when this happens; we may as well count this as the lock being    // acquired and let init continue (though the app may experience other problems    // later).    return;   }   // If we already called lock() but didn't succeed in getting the lock, it's possible the   // app caught the exception and tried again later. As above, there's no real advantage   // to failing here, so only open the lock file if we didn't already open it before.   if (sLockFile == null) {    String dataPath = PathUtils.getDataDirectory();    File lockFile = new File(dataPath, EXCLUSIVE_LOCK_FILE);    try {   // Note that the file is kept open intentionally.     sLockFile = new RandomAccessFile(lockFile, "rw");    } catch (IOException e) {    // Failing to create the lock file is always fatal; even if multiple processes    // are using the same data directory we should always be able to access the file    // itself.     throw new RuntimeException("Failed to create lock file " + lockFile, e);    }   }   // Android versions before 11 have edge cases where a new instance of an app process can   // be started while an existing one is still in the process of being killed. This can   // still happen on Android 11+ because the platfORM has a timeout for waiting, but it's   // much less likely. Retry the lock a few times to give the old process time to fully go   // away.   for (int attempts = 1; attempts <= LOCK_RETRIES; ++attempts) {    try {     sExclusiveFileLock = sLockFile.getChannel().tryLock();    } catch (IOException e) {    // Older versions of Android incorrectly throw IOException when the flock()    // call fails with EAGAIN, instead of returning null. Just ignore it.    }    if (sExclusiveFileLock != null) {     // We got the lock; write out info for debugging.     writeCurrentProcessInfo(sLockFile);     return;    }    // If we're not out of retries, sleep and try again.    if (attempts == LOCK_RETRIES) break;    try {     Thread.sleep(LOCK_SLEEP_MS);    } catch (InterruptedException e) {    }   }   // We failed to get the lock even after retrying.   // Many existing apps rely on this even though it's known to be unsafe.   // Make it fatal when on P for apps that target P or higher   String error = getLockFailureReason(sLockFile);   boolean dieOnFailure = Build.VERSION.SDK_INT >= Build.VERSION_CODES.P     && appContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.P;   if (dieOnFailure) {    throw new RuntimeException(error);   } else {    Log.w(TAG, error);   }  } } private static void writeCurrentProcessInfo(final RandomAccessFile file) {  try {   // Truncate the file first to get rid of old data.   file.setLength(0);   file.writeInt(Process.myPid());   file.writeUTF(ContextUtils.getProcessName());  } catch (IOException e) {   // Don't crash just because something failed here, as it's only for debugging.   Log.w(TAG, "Failed to write info to lock file", e);  } } private static String getLockFailureReason(final RandomAccessFile file) {  final StringBuilder error = new StringBuilder("Using WebView from more than one process at "    + "once with the same data directory is not supported. Https://crbug.com/558377 "    + ": Current process ");  error.append(ContextUtils.getProcessName());  error.append(" (pid ").append(Process.myPid()).append("), lock owner ");  try {   int pid = file.readInt();   String processName = file.readUTF();   error.append(processName).append(" (pid ").append(pid).append(")");   // Check the status of the pid holding the lock by sending it a null signal.   // This doesn't actually send a signal, just runs the kernel access checks.   try {    Os.kill(pid, 0);    // No exception means the process exists and has the same uid as us, so is    // probably an instance of the same app. Leave the message alone.   } catch (ErrnoException e) {    if (e.errno == OsConstants.ESRCH) {     // pid did not exist - the lock should have been released by the kernel,     // so this process info is probably wrong.     error.append(" doesn't exist!");    } else if (e.errno == OsConstants.EPERM) {     // pid existed but didn't have the same uid as us.     // Most likely the pid has just been recycled for a new process     error.append(" pid has been reused!");    } else {     // EINVAL is the only other documented return value for kill(2) and should never     // happen for signal 0, so just complain generally.     error.append(" status unknown!");    }   }  } catch (IOException e) {   // We'll get IOException if we failed to read the pid and process name; e.g. if the   // lockfile is from an old version of WebView or an IO error occurred somewhere.   error.append(" unknown");  }  return error.toString(); }}

lock方法会对webview数据目录中的webview_data.lock文件在for循环中尝试加16次,注释中也说明了这么做的原因:可能出现的极端情况是一个旧进程正在被杀死时一个新的进程启动了,看来Google工程师对这个问题也很头痛;如果加锁成功会将该进程id和进程名写入到文件,如果加锁失败则会抛出异常。所以在android9.0以上检测应用是否存在多进程共用WebView数据目录的原理就是进程持有WebView数据目录中的webview_data.lock文件的锁。所以如果子进程也对相同文件尝试加锁则会导致应用崩溃。

解决方案

目前大部分手机会在应用崩溃时自动重启应用,猜测当手机系统运行较慢时这时就会出现注释中提到的当一个旧进程正在被杀死时一个新的进程启动了的情况。既然获取文件锁失败就会发生崩溃,并且该文件只是用于加锁判断是否存在多进程共用WebView数据目录,每次加锁成功都会重新写入对应进程信息,那么我们可以在应用启动时对该文件尝试加锁,如果加锁失败就删除该文件并重新创建,加锁成功就立即释放锁,这样当系统尝试加锁时理论上是可以加锁成功的,也就避免了这个问题的发生。

private static void handleWebviewDir(Context context) {  if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {   return;  }  try {   String suffix = "";   String processName = getProcessName(context);   if (!TextUtils.equals(context.getPackageName(), processName)) {//判断不等于默认进程名称    suffix = TextUtils.isEmpty(processName) ? context.getPackageName() : processName;    WebView.setDataDirectorySuffix(suffix);    suffix = "_" + suffix;   }   tryLockOrRecreateFile(context,suffix);  } catch (Exception e) {   e.printStackTrace();  } } @TargetApi(Build.VERSION_CODES.P) private static void tryLockOrRecreateFile(Context context,String suffix) {  String sb = context.getDataDir().getAbsolutePath() +    "/app_webview"+suffix+"/webview_data.lock";  File file = new File(sb);  if (file.exists()) {   try {    FileLock tryLock = new RandomAccessFile(file, "rw").getChannel().tryLock();    if (tryLock != null) {     tryLock.close();    } else {     createFile(file, file.delete());    }   } catch (Exception e) {    e.printStackTrace();    boolean deleted = false;    if (file.exists()) {     deleted = file.delete();    }    createFile(file, deleted);   }  } } private static void createFile(File file, boolean deleted){  try {   if (deleted && !file.exists()) {    file.createNewFile();   }  } catch (Exception e) {   e.printStackTrace();  } }

使用此方案应用上线后该问题崩溃次数减少了90%以上。也许Google工程师应该考虑下换一种技术方案检测应用是否存在多进程共用WebView数据目录。

以上是“Android如何解决WebView多进程崩溃的问题”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注编程网精选频道!

--结束END--

本文标题: Android如何解决WebView多进程崩溃的问题

本文链接: https://www.lsjlt.com/news/268916.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Android如何解决WebView多进程崩溃的问题
    小编给大家分享一下Android如何解决WebView多进程崩溃的问题,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!问题在android 9.0系统上如果多个进程...
    99+
    2023-06-14
  • Android 解决WebView多进程崩溃的方法
    目录问题 问题分析 解决方案 问题 在android 9.0系统上如果多个进程使用WebView需要使用官方提供的api在子进程中给webview的数据文件夹设置后缀: Web...
    99+
    2024-04-02
  • 如何解决win10系统崩溃问题
    这篇文章主要介绍了如何解决win10系统崩溃问题,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。首先,先重启电脑然后,找到启动修复的按钮,然后对系统进行修复。然后对电脑进行系统...
    99+
    2023-06-27
  • 如何解决使Eclipse崩溃的JVM terminated问题
    这期内容当中小编将会给大家带来有关如何解决使Eclipse崩溃的JVM terminated问题,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。本文将介绍如何解决JVM terminated令Eclipse...
    99+
    2023-06-17
  • 如何解决腾讯云服务器崩溃问题
    1. 确认服务器是否真的崩溃 在处理服务器崩溃问题之前,首先需要确认服务器是否真的崩溃了。可以通过以下几种方式来确认: 尝试通过 SSH 连接服务器,如果连接失败,则可能是服务器崩溃了。 查看服务器的监控数据,如果 CPU 使用率、内存...
    99+
    2023-10-26
    腾讯 如何解决 服务器
  • ubuntu安装程序崩溃如何解决
    如果Ubuntu安装程序崩溃,您可以尝试以下几种解决方法:1. 重新启动系统:有时候系统出现问题可能只是临时的,重新启动可以解决一些...
    99+
    2023-08-29
    ubuntu
  • 怎么解决NodeJS服务总是崩溃的问题
    这篇文章主要介绍了怎么解决NodeJS服务总是崩溃的问题,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。许多人都有这样一种映像,NodeJS比较快; 但是因为其是单线程,所以它...
    99+
    2023-06-14
  • php如何解决进程太多的问题
    小编给大家分享一下php如何解决进程太多的问题,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!php进程太多的解决办法:1、通过“ps -ef  | wc...
    99+
    2023-06-25
  • win10方舟生存进化崩溃如何解决
    这篇文章主要讲解了“win10方舟生存进化崩溃如何解决”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“win10方舟生存进化崩溃如何解决”吧!方法一、更新显示驱动程序 由于错误信息本身指示错误...
    99+
    2023-07-01
  • 如何解决chm在WIN7下崩溃生成chw文件的问题
    安装有Visual Studio的机器,可以调试一下,看到调用栈到了hhctrl.ocx控件处出问题了。 以下按网上的办法解决此问题,打开cmd窗口,按照下面次序在运行: regsvr32 jscript.dll reg...
    99+
    2023-05-25
    chm 文件 WIN7 问题 chw文件
  • JVM崩溃的原因及如何解决
    这篇文章将为大家详细讲解有关JVM崩溃的原因及如何解决,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。前些天,搞JNI的时候,报了个JVM崩溃的错。错误信息如下:## An ...
    99+
    2023-06-17
  • 如何解决Android中WebView的input上传照片兼容问题
    小编给大家分享一下如何解决Android中WebView的input上传照片兼容问题,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!问题前几天接到的一个需求,是关于...
    99+
    2023-05-30
    android webview input
  • Android 解决WebView无法上传文件的问题
    Android 解决WebView无法上传文件的问题Android原生的WebView并不支持上传文件,需要我们自己实现相应的方法。于是我把工作中的相关代码记录下来。下次直接拿来用就行了。一点一滴都是经验。 1。需要定义三个变量 priva...
    99+
    2023-05-30
    android webview roi
  • Go语言使用defer+recover解决panic导致程序崩溃的问题
    案例:如果我们起了一个协程,但这个协程出现了panic,但我们没有捕获这个协程,就会造成程序的崩溃,这时可以在goroutine中使用recover来捕获panic,进行处理,这样主...
    99+
    2024-04-02
  • 怎么解决CSS崩溃的父母有浮动子女问题
    本篇内容介绍了“怎么解决CSS崩溃的父母有浮动子女问题”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成! 答...
    99+
    2024-04-02
  • C#开发中如何处理程序崩溃和死锁问题
    C#开发中如何处理程序崩溃和死锁问题,需要具体代码示例在C#开发过程中,程序崩溃和死锁问题是常见的挑战。处理这些问题是保证程序运行稳定和高效的关键,因此,本文将介绍如何处理程序崩溃和死锁问题,并提供一些具体的代码示例。程序崩溃问题处理程序崩...
    99+
    2023-10-22
    异常处理 崩溃恢复 死锁解决
  • 如何解决react-native WebView返回处理问题
    这篇文章主要介绍了如何解决react-native WebView返回处理问题,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。1.前言项目中有...
    99+
    2024-04-02
  • 记一次线程爆满导致服务器崩溃的问题排查及解决
    目录问题介绍1. 重启服务器2. 修改最大线程数3. 查找线程最大的java程序4. 导出问题程序的线程日志5. 找到问题代码6. 解决方案问题介绍 测试服务器突然无法连接,ssh登...
    99+
    2022-11-13
    线程爆满 服务器崩溃 服务器崩溃排查
  • 解决pytorch trainloader遇到的多进程问题
    pytorch中尝试用多进程加载训练数据集,源码如下: trainloader = torch.utils.data.DataLoader(trainset, batch_siz...
    99+
    2024-04-02
  • win11资源管理器不停的崩溃如何解决
    如果Windows 11的资源管理器不停地崩溃,你可以尝试以下几种方法来解决问题:1. 重启电脑:有时候,资源管理器崩溃可能只是暂时...
    99+
    2023-08-22
    win11
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作