一个WebView Native Crash分析过程,居然是字体库引入的Bug

背景

本人使用的字体库是:https://github.com/InflationX/Calligraphy,这个库可以hook所有的TextView更换到我们需要的字体样式。

StackTrace:

2019-05-17 11:53:29.836 W/System.err: android.view.InflateException: Binary XML file line #32: Binary XML file line #32: Error inflating class TextView
2019-05-17 11:53:29.836 W/System.err: Caused by: android.view.InflateException: Binary XML file line #32: Error inflating class TextView
2019-05-17 11:53:29.841 W/System.err: Caused by: android.content.res.Resources$NotFoundException: Unable to find resource ID #0x20b017c
2019-05-17 11:53:29.841 W/System.err:     at android.content.res.ResourcesImpl.getResourceEntryName(ResourcesImpl.java:291)
2019-05-17 11:53:29.841 W/System.err:     at android.content.res.Resources.getResourceEntryName(Resources.java:2017)
2019-05-17 11:53:29.841 W/System.err:     at io.github.inflationx.calligraphy3.Calligraphy.matchesResourceIdName(Calligraphy.java:94)
2019-05-17 11:53:29.841 W/System.err:     at io.github.inflationx.calligraphy3.Calligraphy.isActionBarTitle(Calligraphy.java:57)
2019-05-17 11:53:29.841 W/System.err:     at io.github.inflationx.calligraphy3.Calligraphy.getStyleForTextView(Calligraphy.java:33)
2019-05-17 11:53:29.841 W/System.err:     at io.github.inflationx.calligraphy3.Calligraphy.onViewCreatedInternal(Calligraphy.java:139)
2019-05-17 11:53:29.841 W/System.err:     at io.github.inflationx.calligraphy3.Calligraphy.onViewCreated(Calligraphy.java:117)
2019-05-17 11:53:29.841 W/System.err:     at io.github.inflationx.calligraphy3.CalligraphyInterceptor.intercept(CalligraphyInterceptor.java:19)
2019-05-17 11:53:29.841 W/System.err:     at io.github.inflationx.viewpump.internal.-InterceptorChain.proceed(-InterceptorChain.kt:30)
2019-05-17 11:53:29.841 W/System.err:     at io.github.inflationx.viewpump.ViewPump.inflate(ViewPump.kt:36)
2019-05-17 11:53:29.841 W/System.err:     at io.github.inflationx.viewpump.internal.-ViewPumpLayoutInflater$WrapperFactory2.onCreateView(-ViewPumpLayoutInflater.kt:350)
2019-05-17 11:53:29.841 W/System.err:     at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:811)
2019-05-17 11:53:29.842 W/System.err:     at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:769)
2019-05-17 11:53:29.842 W/System.err:     at android.view.LayoutInflater.rInflate(LayoutInflater.java:902)
2019-05-17 11:53:29.842 W/System.err:     at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:863)
2019-05-17 11:53:29.842 W/System.err:     at android.view.LayoutInflater.rInflate(LayoutInflater.java:905)
2019-05-17 11:53:29.842 W/System.err:     at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:863)
2019-05-17 11:53:29.842 W/System.err:     at android.view.LayoutInflater.inflate(LayoutInflater.java:554)
2019-05-17 11:53:29.842 W/System.err:     at io.github.inflationx.viewpump.internal.-ViewPumpLayoutInflater.inflate(-ViewPumpLayoutInflater.kt:53)
2019-05-17 11:53:29.842 W/System.err:     at android.view.LayoutInflater.inflate(LayoutInflater.java:461)
2019-05-17 11:53:29.842 W/System.err:     at io.github.inflationx.viewpump.internal.-ViewPumpLayoutInflater.inflate(-ViewPumpLayoutInflater.kt:44)
2019-05-17 11:53:29.842 W/System.err:     at android.view.LayoutInflater.inflate(LayoutInflater.java:383)
2019-05-17 11:53:29.842 W/System.err:     at cJL.getView(PG:19)
2019-05-17 11:53:29.842 W/System.err:     at android.widget.AbsListView.obtainView(AbsListView.java:3219)
2019-05-17 11:53:29.842 W/System.err:     at android.widget.ListView.onMeasure(ListView.java:1326)
2019-05-17 11:53:29.842 W/System.err:     at android.view.View.measure(View.java:24954)
2019-05-17 11:53:29.842 W/System.err:     at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:7134)
2019-05-17 11:53:29.842 W/System.err:     at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1535)
2019-05-17 11:53:29.842 W/System.err:     at android.widget.LinearLayout.measureVertical(LinearLayout.java:825)
2019-05-17 11:53:29.842 W/System.err:     at android.widget.LinearLayout.onMeasure(LinearLayout.java:704)
2019-05-17 11:53:29.842 W/System.err:     at android.view.View.measure(View.java:24954)
2019-05-17 11:53:29.842 W/System.err:     at cMB.d(PG:53)
2019-05-17 11:53:29.843 W/System.err:     at cJO.a(PG:8)
2019-05-17 11:53:29.843 W/System.err:     at cwX.(PG:11)
2019-05-17 11:53:29.843 W/System.err:     at org.chromium.content.browser.input.SelectPopup.show(PG:40)
2019-05-17 11:53:29.843 W/System.err:     at android.os.MessageQueue.nativePollOnce(Native Method)
2019-05-17 11:53:29.843 W/System.err:     at android.os.MessageQueue.next(MessageQueue.java:326)
2019-05-17 11:53:29.843 W/System.err:     at android.os.Looper.loop(Looper.java:181)
2019-05-17 11:53:29.843 W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:7072)
2019-05-17 11:53:29.843 W/System.err:     at java.lang.reflect.Method.invoke(Native Method)
2019-05-17 11:53:29.843 W/System.err:     at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
2019-05-17 11:53:29.843 W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:964)
2019-05-17 11:53:29.847 E/WifiConnectivityMonitor: msg.arg1 != mRssiFetchToken
2019-05-17 11:53:29.854 A/chromium: [FATAL:jni_android.cc(249)] Please include Java exception stack in crash report
2019-05-17 11:53:29.856 A/libc: Fatal signal 5 (SIGTRAP), code 1 (TRAP_BRKPT), fault addr 0xe6735000 in tid 10822 (roid.production), pid 10822 (roid.production)
2019-05-17 11:53:29.938 I/crash_dump32: obtaining output fd from tombstoned, type: kDebuggerdTombstone
2019-05-17 11:53:29.942 I//system/bin/tombstoned: received crash request for pid 10822
2019-05-17 11:53:29.944 I/crash_dump32: performing dump of process 10822 (target tid = 10822)
2019-05-17 11:53:29.965 A/DEBUG: *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
2019-05-17 11:53:29.965 A/DEBUG: Build fingerprint: 'samsung/gta3xleea/gta3xl:9/PPR1.180610.011/T515XXU1ASCK:user/release-keys'
2019-05-17 11:53:29.965 A/DEBUG: Revision: '4'
2019-05-17 11:53:29.965 A/DEBUG: ABI: 'arm'
2019-05-17 11:53:29.965 A/DEBUG: signal 5 (SIGTRAP), code 1 (TRAP_BRKPT), fault addr 0xe6735000
2019-05-17 11:53:29.965 A/DEBUG: Abort message: '[FATAL:jni_android.cc(249)] Please include Java exception stack in crash report
    '
2019-05-17 11:53:29.965 A/DEBUG:     r0  00000000  r1  c88e12a0  r2  00000400  r3  00000000
2019-05-17 11:53:29.965 A/DEBUG:     r4  ffdc3108  r5  d0ee14d8  r6  e70683c8  r7  ffdc30ec
2019-05-17 11:53:29.965 A/DEBUG:     r8  e706dd94  r9  ffdc3544  r10 ffdc3540  r11 ffdc353c
2019-05-17 11:53:29.965 A/DEBUG:     ip  ffdc310c  sp  ffdc30d8  lr  cf8f32d1  pc  cf8f33ba
2019-05-17 11:53:30.054 A/DEBUG: backtrace:
2019-05-17 11:53:30.054 A/DEBUG:     #00 pc 023003ba  /data/app/com.android.chrome-1HS2RCE7TlSpdPbYl-VZLg==/base.apk (offset 0x1ee5000)

从上报来看,都是三星手机,而且都是Android 9手机,崩到Native Crash去了。

 

分析过程

一开始以为是oom问题引起的,(因为最近很多OOM上报)

带着疑问去寻找根源,打开用户的路径,找到两个用户分析:

我们根据用户的ui action,分析了一下,用户在崩溃之前,没有做图片的操作,看到内存也比较充足,

因此,我们可以推断跟oom没啥关系。

并且,我用其他三星手机测试过大图,并没有发现oom问题。

因此,oom的原因可以排除。

于是请教了WebView 内核开发的同学,给了一个文章,提供了一些思路。

可以得出以下这样的结论:

实际上在最上面可以看到一个jni报的异常,说明上面有java异常没有正确处理。事实上以上问题在使用系统webview的时候也同样会发生。

这里有很多人会产生这样一个误解:java发生异常肯定是崩在java里的,不会崩到native里。在大部分情况下这句话是正确的,但是在native通过jni调用java方法时就不正确了。

在jni调用java方法时,因为jni没有try...catch的机制,如果发生java异常,后续的代码不会停止,仍然会继续执行。而为了避免程序发生重大问题,在jni中一般会调用ExceptionCheck来检查java代码运行有没有发生异常。

如果发生了异常,可以调用ExceptionDescribe函数打印这个异常的堆栈信息,然后再调用ExceptionClear函数清除异常堆栈信息的缓冲区(如果不清除,后面调用ThrowNew抛出的异常堆栈信息会覆盖前面的异常信息),最后调用ThrowNew函数手动抛出一个java.lang.Exception异常。但是在JNI中抛出未捕获的异常与Java的异常处理机制不一样,在JNI中并不会立即终止本地方法的执行,而是继续执行后面的代码,这种情况下仍然有可能导致问题的产生,这种情况下就需要手动处理。所以大多数情况下,如果在jni中检测到发生了java异常没catch住,一般都会选择主动崩溃。

 

于是根据原始日志,应该就是15691这个线程崩了,报的是这个字体第三方库崩了;那就是字体库的问题了。

一个WebView Native Crash分析过程,居然是字体库引入的Bug_第1张图片

 

这种问题,线上可能不好太定位哪里出错了,也没找到复现路径,于是看看这个库有没有人去提到这个事情;

于是马上这个库的isues去看看,发现果然有人提到这个问题:

https://github.com/InflationX/Calligraphy/issues/30

产生的问题很类似,弹出一个popwindow,然后就会出现问题。

 

直接找关键源码

cpp的定义:

https://doss-gitlab.eidos.ic.i.u-tokyo.ac.jp/liujp-arch/chromium/blob/735d96ce1da80955647f0cb0389214a6f97962e9/content/browser/android/text_suggestion_host_android.h

一个WebView Native Crash分析过程,居然是字体库引入的Bug_第2张图片

 

Java层的调用:

https://chromium.googlesource.com/chromium/src/+/66.0.3359.158/content/public/android/java/src/org/chromium/content/browser/input/TextSuggestionHost.java?autodive=0%2F%2F%2F%2F%2F

 

一个WebView Native Crash分析过程,居然是字体库引入的Bug_第3张图片

 

 

可是,已经有人提了merge,但是一直没有合进去:(这??尴尬)

https://github.com/InflationX/Calligraphy/pull/31/commits/09eaf23cee3fe5be0b6687c600da79df3074cd59,导致3.1.12一直没发出去。。。

而我们使用自定义字体库的时候,刚好是10.9,没吃到这个螃蟹(10.23)。

 

|一个WebView Native Crash分析过程,居然是字体库引入的Bug_第4张图片

 

 

根本原因

​context.getResources().getResourceEntryName(resId);​

 Caused by: android.content.res.Resources$NotFoundException: Unable to find resource ID #0x20b0031>

获取资源id它的名字 在三星 系统9手机有可能是空的。在其他手机测试未发现异常。

具体的原因,猜测是三星这个id在编译之后地址偏移或者没有了,深入的原因还需要更深入的看看。

 

为了证实最后的结论,我在输入的时候模拟出现三星的suggestion功能。操作步骤是,输入几个字母,点击空格,几个字母成为单词会有下划线,并且出现这个PopupWindow,然后再点击PopupWindow上面提示的单词。问题就会复现!

一个WebView Native Crash分析过程,居然是字体库引入的Bug_第5张图片

 

 

一个WebView Native Crash分析过程,居然是字体库引入的Bug_第6张图片

跟我们的错误堆栈完全吻合!!

 

思考 :

 使用别人的第三方库,确实存在着会有一些不可预知的问题。如何尽早的发现问题?

个人的感觉使用别人的第三方库首先要多思考稳定性问题,是否有一些场景没考虑到,可以通过查看issues和mr去多了解一下,并且在接入的时候,可以多做一些技术调研,是否有优化的地方。

 

你可能感兴趣的:(android,java,native,crash,android)