最近在将工程海外版targetVersion升到10之后发现线上出现一个数量级很高的崩溃:
"Using WebView from more than one process at once with the same data directory is not supported. https://crbug.com/558377 : Current process...“
参考了谷歌的Webview.setDataDirectorysuffix()方案,却引入了“webview already inited”WebView已经初始化的新问题,最后经过不断的分析,终于敲定
把Webview.setDataDirectorysuffix()放在application的attach生命周期
解决了这个问题,下面的复盘供大家参考。
场景复盘:
-
在一开始为了定位发生的场景花了不少时间,最后推断是应用首次初始化的时候发生的,如何分析的:
- 没有用户在反馈系统里反馈这个问题
- 崩溃次数和发生用户比例几乎就是1:1
- “webview already inited”改崩溃信息也反映出发生时刻是在初始化
-
从源码的角度分析谷歌Webview.setDataDirectorysuffix()方案到底有没有用
首先这里还有个疑惑,为什么这个崩溃只在targetVersion升级后发生在高版本,通过阅读源码发现:
AwDataDirLock.java
我们知道andriod9(P)版本开始WebView使用的是独立进程,所以此处可以认为谷歌为了规范这个使用在系统版本和目标版本在9和9以上如果WebView使用不当就会抛出多进程异常,具体原因如下:
carashReason
可见此处如果sLockFile加锁失败,就会抛出之前的异常,此处的sLockFile指向Webview的缓存目录,路径是:/data/data/包名/cache/app_webview目录下。
这也解释了为什么此处谷歌直接抛出多进程异常,因为这是WebView的私有缓存目录,通常只有WebView自身的操作才会读写,只有在多进程WebView启动的情况下,前一个进程还在锁定缓存文件目录操作,后一个进程也要加锁,才会失败。 -
解决方案思考
-
最合适的方案应该是规范WebView的使用,不要给WebView单独开进程,都使用系统独立进程使用WebView但是在项目中分析是第三方sdk引起的,不好推进修改
-
Webview.setDataDirectorysuffix()方案为何失败,Webview.setDataDirectorysuffix()是为每个进程设置不同的目录,确实解决了上述问题,但是分析源码的过程中,我们知道这个过程是发生在WebView对缓存目录加载的过程,这和线上场景分析发生在应用首次初始化是吻合的,所以我们要在缓存目录加载加载之前设置,于是最终的方案:
把Webview.setDataDirectorysuffix()放在application的attach生命周期
这样就可以保证在任何业务驱使的Webview初始化都在Webview.setDataDirectorysuffix()之后了。
-
网友评论