写点什么

android 开发 加载 so 库的解析和出现的各种错误分析

作者:小小Code
  • 2022 年 5 月 11 日
  • 本文字数:3179 字

    阅读完需:约 10 分钟

八.那我们是不是只放一种 armeabi 就够了?


=======================


事实上并不是:这不只影响到函数库的性能和兼容性。x86 设备能够很好的运行 ARM 类型函数库,但并不保证 100%不发生 crash,特别是对旧设备。64 位设备(arm64-v8a, x86_64, mips64)能够运行 32 位的函数库,但是以 32 位模式运行,在 64 位平台上运行 32 位版本的 ART 和 Android 组件,将丢失专为 64 位优化过的性能(ART,webview,media 等等)。


九.如何查看我的 android 手机属于什么架构的?


=========================


进入命令行:


第一步:输入 adb shell 回车


第二步:cat /proc/cpuinfo 回车


下面打印出的信息里面有 Processor 如下图:



十.到底如何适配,每种适配方案区别?


==================

CPU 之间的架构兼容

ARMv5 设备:只支持 armeabi


ARMv7 设备:支持 armeabi 和 armeabi-v7a


ARMv8 设备:支持 armeabi-v7a、armeabi 和 arm64-v8a


X86 设备:支持 armeabi(性能有所损耗) 和 x86


x86_64 设备:支持 x86 和 x86_64


mips 设备: 支持 mips


mips_64 设备:支持 mips 和 mips_64

Android 中设备加载 so 策略

不同 CPU 架构的 android 手机加载时会在 libs 下找自己对应的目录,从对应的目录下寻找需要的.so 文件;如果没有对应的目录,就会去 armeabi 下去寻找,如果已经有对应的目录,却如果没有找到对应的.so 文件,也不会去 armeabi 下去寻找了。


以 x86 设备为例,x86 设备会在项目中的 libs 文件夹寻找是否含有 x86 文件夹,如果含有 x86 文件夹,则默认为该项目有 x86 对应的 so 可运行文件,只有 x86 文件夹而文件夹下没有 so,程序运行也是会出现 find library returned null 的错误的;如果工程本身不含有 x86 文件夹,则会寻找 armeabi 或者 armeabi-v7a 文件夹,兼容运行。以 armeabi-v7a 设备为例,该 Android 设备当然优先寻找 libs 目录下的 armeabi-v7a 文件夹,同样,如果只有 armeabi-v7a 文件夹而没有 so 也是会报错的;如果找不到 armeabi-v7a 文件夹,则寻找 armeabi 文件夹,兼容运行该文件夹下的 so,但是不能兼容运行 x86 的 so。所以项目中如果只含有 x86 的 so,在 armeabi 和 armeabi-v7a 也是无法运行的。以上就是不同 CPU 架构运行时加载 so 的策略。


目前主流的 Android 设备主要是 armeabi-v7a 架构的,然后是 x86 和 armeabi 了。如果同时包含了 armeabi, armeabi-v7a 和 x86,所有设备都可以运行,程序在运行的时候去加载不同平台对应的 so,这是较为完美的一种解决方案,但是有时候为了减少 apk 的大小,不会同时设置 armeabi, armeabi-v7a 和 x86。根据不同的情况,可以进行不同的适配,


**1.只适配 armeabi-v7a,**因为目前主流机型是 ARMv7,并且 ARMv8 设备也向下兼容了 armeabi-v7a,


Facebook、WhatsApp、王者荣耀等就是只适配了 armeabi-v7a。(Google play store 下载 Native libs Monitor 进行查看)。


2.只适配 armeabi,因为 ARMv7 、ARMv8 还是 x86 都兼容 armeabi,但是性能都会有些损耗,例如 ARMv7 支持硬件浮点运算等没法体现,x86 支持 armeabi 同样具有相应的损耗。


3.同时适配 armeabi-v7a 和 armeabi,既能够支持所有 ARM 架构,同时又能具有 ARMv7 支持硬件浮点运算等特性,例如 Line 等应用


4.同时适配 x86 和 armeabi,既能支持所有 ARM 架构,又能支持 x86 架构,唯一的缺点就是没有了 ARMv7 支持硬件浮点运算等一系列特性,例如 QQ


5.同时适配 armeabi, armeabi-v7a 和 x86,在性能方面来说是较为完美的方案,只是 APK 的大小也会随之的变大


6.其他的一些方案,例如微信只适配了 armeabi,但是对于某些需要利用 ARMv7 支持硬件浮点运算等一系列特性的操作,在 armeabi 目录下存在 v7 对应的 so 文件,通过代码判断加载不同的 so 文件。即达到了减少 APK 大小的目的,又能达到适配 ARMv7 等架构以便使用其架构的一些新特性的目的。


十一.so 库开发过程中的一些错误汇总!(后续补充)


=========================


基本上大部分关于 so 库的错误 都是? ?java.lang.UnsatisfiedLinkError


官方解释 ?? ?Throw if the java Virtural Machine cannot find an appropriate native-language definition of method declared native 意思就是 JVM 找不到 native method 的 native 实现!


所以 《Android 学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》无偿开源 徽信搜索公众号【编程进阶路】 看到这个错误,一般常见的几种情况分析。


1、低级错误——根本木有 SO,你加载个球啊!




code ?? ?System.loadLibrary(Bugly);


libs ?? ?空


运行设备 ?? ?Android ARM 设备


运行结果 ?? ?Crash!java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[[zip file “/data/app/com.tencent.bugly.demo-1/base.apk”],nativeLibraryDirectories=[/vendor/lib, /systemb]]] couldn’t find “libBugly.so”


原因分析 ?? ?apk 安装时,系统会把 apk 中 libs 目录下 armeabi 的 SO 拷贝到应用的私有目录下。所以 libs 里没有放入 SO,运行时肯定找不到 SO。


修复方式 ?? ?添加 SO:libs\armeabi\libBugly.so 或加载代码注释掉://System.loadLibrary(Bugly) ;


2、进阶错误——根本木有 X86 的 SO,在 X86 的设备上你加载个球啊!




code ?? ?System.loadLibrary(Bugly);


libs ?? ?libs\armeabi\libBugly.so


运行设备 ?? ?Android X86 设备


运行结果 ?? ?Crash!java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[[zip file “/data/app/com.tencent.bugly.demo-1/base.apk”],nativeLibraryDirectories=[/vendor/lib, /systemb]]] couldn’t find “libBugly.so”


原因分析 ?? ?apk 安装时,x86 设备上系统会把 apk 中 libs 目录下 x86 的 SO,拷贝到应用的私有目录下。虽然 libs 下有 armeabi 的 SO,但没有放入 x86 的 SO,运行时还是找不到 libbugly.so。


修复方式 ?? ?添加 SO:libs\x86\libBugly.so 或加载代码注释掉://System.loadLibrary(Bugly) ;


3、大坑——尼玛,好难发现!




libs ?? ?libs\armeabi\libBugly.solibs\armeabi\libBugly2.solibs\armeabi-v7a\libBugly.so


运行设备 ?? ?Android ARMv7 设备


运行结果 ?? ?Crash!java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[[zip file “/data/app/com.tencent.bugly.demo-1/base.apk”],nativeLibraryDirectories=[/vendor/lib, /systemb]]] couldn’t find “libBugly2.so”


原因分析 ?? ?apk 安装时,系统会把 apk 中 libs 目录下 armeabi-v7a 整个目录下的 SO 拷贝到应用的私有目录下。因为 armeabi-v7a 下没有放入 libBugly2.so,运行时找不到 libBugly2.so。不同的工具兼容的 CPU 架构不一致,就容易出这个错误了!例如:


libBugly.so 提供 armeabi、armeabi-v7a、x86 三种。


但其它产品可能只提供了 armeabi。


如果把这些 so 都直接拷贝进 apk,就会因为上述的原因直接 crash,会误以为该 Crash 是因为不同产品的 so 不能兼容导致的!


修复方式 ?? ?添加 SO:libs\armeabi-v7a\libBugly2.so 或直接删除 armeabi-v7a 目录,arm 设备上系统会自动选择 armeabi


4、天坑——尼玛,巨难发现!




java.lang.UnsatisfiedLinkError 中 couldn’t find “XX.so”的占比非常高,上面提的三个场景都是这种错误!


但你见过下面这种错误吗?


java.lang.UnsatisfiedLinkError:dlopen failed: “**/*/arm/*.so” has unexpected e_machine: 3


code ?? ?if(getArch().contain(“arm”)){//只在 arm 下加载 System.loadLibrary(Bugly) ;}


libs ?? ?libs\armeabi\libBugly.so 坑爹实习生放入了 x86 编译的 libBugly.so(同名很容易出错)


运行设备 ?? ?Android ARM 设备


运行结果 ?? ?Crash!java.lang.UnsatisfiedLinkError: dlopen failed: “/data/app/com.tencent.bugly.crashreport.demo-2/lib/arm/libBugly.so” has unexpected e_machine: 3


原因分析 ?? ?apk 安装时,系统把 armeabi 下的 libBugly.so 放入应用的私有目录中了!但这个 libBugly.so 不是 arm 的,而是 x86 编译的 libBugly.so 运行时,系统检察 ELF 文件中的 e_machine 字段的值,跟 arm 的不匹配,就会抛出这个异常了!

用户头像

小小Code

关注

还未添加个人签名 2022.04.20 加入

还未添加个人简介

评论

发布
暂无评论
android开发 加载so库的解析和出现的各种错误分析_android_小小Code_InfoQ写作社区