ReactNative关于32位和64位SO库混合引入Crash解决方案
Posted YongHui_Luo
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ReactNative关于32位和64位SO库混合引入Crash解决方案相关的知识,希望对你有一定的参考价值。
问题描述
现有项目集成ReactNative后,在你的个别测试机上运行成功,只是踏入RN大门的第一步,对于已经进入稳定迭代期的产品,集成后需要对各种机型进行测试,保证原有逻辑的基础上,去验证会不会由于集成RN引发新的问题。
很幸运的是,当使用Smartisan M1
测试我的项目时,出现如下的Crash信息。
java.lang.UnsatisfiedLinkError: dlopen failed: "xxx/libgnustl_shared.so" is 32-bit instead of 64-bit
在解决问题的过程中,有同学也遇到的了如下的问题,和上述的Crash,属于同一原因导致,也可以用下面将会介绍的方法解决。
java.lang.UnsatisfiedLinkError: could find DSO to load: libreactnativejni.so
思路分析
上面的两种Error,反馈给我们的信息就是当程序要使用相应的so
库时,在当前installed apk
中并没有找到。为什么没有找到?另外还不是必现的问题,只是在个别的手机上会出现。好的,准备好和慧兄一起来分析这个问题。
Native Libs Monitor
首先,推荐一个神器,名称Native Libs Monitor
是一款手机App下载地址,也可以在国内应用市场下载。她是一个本地库监视器,可以查看应用信息、应用直接添加的so
库,应用使用的依赖库中添加的so
。省去解包的过程,并且能够帮助分析问题,以我的App为例进行分析。
上图是当Crash出现的时候,使用Native Libs Monitor
分析的本地库的包含情况。
Native Libraries inside APK:APK内部应该包含的所有so库的展示列表
Native Libraries installed : 安装包的Libs目录下,包含的so库。
上图中可以明显看出,标示为2的区域,成功打入到安装包Libs目录下的so库只有libimagepipeline.so
。这里留下一个疑问,为什么会出现这种情况?
正常区域2和区域3的so库应该是相同的,这样程序才能正常运行,如同优酷APK的分析结果。
使用的所有依赖库,都会成批打入到APK的Libs文件夹下。
手机ABI/CPU型号
上面的问题,我们先预留,然后分享一条命令用来查看手机的ABI/CPU型号。
adb shell cat /system/build.prop | grep “product”
在Smartisan M1
手机上执行命令的结果如下:
OK,可以看到
ro.product.cpu.abilist64=arm64-v8a
ro.product.cpu.abilist32=armeabi-v7a,armeabi
小结论
通过上面的分析,可以预测一个结论:
android不能同时加载32和64位本机库。 如果您至少有一个依赖库使用ARM64支持编译的扩展,而另外一些依赖库仅支持ARM32,就会出现问题。 系统将检测ARM64依赖关系,加载它,然后拒绝加载仅ARM32的so
库,就可能导致应用程序崩溃。
项目中只有libimagepipeline.so
有arm64-v8a
支持编译的扩展,Smartisan M1
手机发现有64位的本机库,就不会再去加载32位的本机库,所以在Native Libraries installed
区就只能看到libimagepipeline.so
一个so
库。也因此会报我们开篇提到的两个缺省so
库的Error,也因此回复了为什么只有一个so
库的问题。
解决方案
既然找到了问题所在,就好解决了,两种方案。
第一种方案
所有引入的第三方依赖库,都需要提供arm64-v8a
型号的支持。目前这种比较难以实现。
第二种方案
在project的root目录下的build.gradle
中添加如下代码。
defaultConfig
minSdkVersion 16
targetSdkVersion 21
ndk
abiFilters "armeabi-v7a","x86"
packagingOptions
exclude "lib/arm64-v8a/libimagepipeline.so"
注:需要exclude的so库,是项目中
arm64-v8a
文件夹中的,例如通过上面的分析,我的项目中64位支持的是libimagepipeline.so
,所以通过如上代码进行编译排除。
OK,问题解决。如果你发现文章中有表示不准确的地方,欢迎留言指正,3Q。
以上是关于ReactNative关于32位和64位SO库混合引入Crash解决方案的主要内容,如果未能解决你的问题,请参考以下文章
在 Java 应用程序中混合运行 32 位和 64 位本机库
尝试在 OS X 上为 32 位和 64 位编译 GNU 库
将 32 位和 64 位 .so 文件与 g++ 链接以用于 c++ 程序