一、事情是这样的
我正在热火朝天地吃着面的时候呢,老大在群里 @ 了我一下,吓得我碗都掉面里了。
于是无知的我为了体验一下这个 Bug,就把神秘代码复制直接发群里了。发完之后,点了点,戳了戳,发现没卡死呀。
但是等了半响,突然察觉到事情有些不太对劲。
对不起🧎♂️
二、“卡死”是怎么产生的
cue 完之后我们来看一下这个问题。
我在 Pixel2 (8.1.0) 设备上用微信 8.0.7 重现了这个问题,但是之前在 Redmi Note 3 (5.0.2) 设备上用微信 8.0.3 版本却并没有出现卡死的情况。实际上,几乎所有版本的微信都有这个问题,之所以在红米手机上没有出现,是与其系统版本有关系,这一点会在下文中详细说明。
*注意后续分析过程的所有源码均是基于 android-8.1.0_r39 进行的,因为我手里这台设备刚好是 8.1.0 的系统,这样分析过程中的行号能够更好地匹配上。
接着,从设备中取出 trace 文件进行分析,这里有几种方式:
○ 如果设备 root 了,直接从 /data/anr 目录获取即可。
○ 如果设备没有 root,可以通过 adb bugreport 获取,在解压后的 FS/data/anr 目录中。
通过 trace 文件,我们大致可以做出猜测:ANR 的发生是因为在 nextSpanTransition 的上层调用上出现了死循环。
于是我们可以一层一层往上找代码。
在 android.text.TextLine 的 getOffsetBeforeAfter[1] 方法中发现了一个 while true,它来自 getOffsetToLeftRightOf 方法第