具体的报错是下面这样的:

java.lang.UnsatisfiedLinkError: dlopen failed: cannot locate symbol "CBB_add_u16_length_prefixed" referenced by "/system/lib/libssl.so"

这两天有用户反映在 华为的平板设备(Android 8.0) 上出现闪退的问题,我第二天就到现场调试,发现是在调用一个合作方的 库的时候报错闪退了。具体的报错就是上面的内容。

从字面上来看应该是在使用 libssl.so 的时候找不到 CBB_add_u16_length_prefixed 这个东西,然后就开始了一通百度,bing 搜索,但是都没有找到有用的东西,很多都是其他 so 报错。

后面 Google 搜索,确实找到一些相关的东西,是在某个 github 上面的问题上,但那是一个 c 代码的库,最后的解决方案也是在修改一些编译的配置,但我用的是合作方的库,而且好几年没有更新维护了,想要让他们进行修改进行适配估计是难搞咯。

没有找到一个合适的解决方案,这也是我作这个笔记的原因,希望帮助到其他有这个问题的人。

后面继续用 Google 进行搜索,找到一个 Android 官网的变更说明,大家有兴趣的可以看看,Android 6.0 变更说明。没有梯子的同学,我把相关的内容复制出来了,在下面:

Android 正在从使用 OpenSSL 库转向使用 BoringSSL 库。如果您要在应用中使用 Android NDK,请勿链接到并非 NDK API 组成部分的加密库,如 libcrypto.so 和 libssl.so。这些库并非公共 API,可能会在不同版本和设备上毫无征兆地发生变化或出现故障。此外,您还可能让自己暴露在安全漏洞的风险之下。请改为修改原生代码,以通过 JNI 调用 Java 加密 API,或静态链接到您选择的加密库。

就是说 Android 要进行 libcrypto 和 libssl 这两个库的迁移,告诉开发者后面不要直接使用这两个 so 库了。也就是说,这个库还是存在的,但是库的内容已经不是之前的 OpenSSL 了,所以可能出现,找不到某个 "symbol" 的问题。

当时也不肯定就是这个问题,但是不试一下怎么知道呢?

后面就从网上拿了一个编译好的 OpenSSL 版本的 libssl.so 。然后再 System.loadLibrary("ssl"); 加载进来,后面就好了!一切运行正常。

但是作为一个 NDK 方面的小白,不知道这样做后面会不会有什么隐患,还希望知道的大佬出来指导一下。

最后附上找到编译好的 libssl.so 的地方:OpenSSL 版本的 libssl.so。clone 下来之后,可以在 OpenSSL > app > alley > lib 目录下找到对应的文件。

由于 github 没有梯子的同学下载速度有些感人,于是我把已经下载好的文件分享一下: 百度云下载

另外,有需要的同学可以去编译一遍 OpenSSL ,项目地址在 : OpenSSL

好了,就这样吧。