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

本文涉及的产品
云解析DNS-重点域名监控,免费拨测 20万次(价值200元)
简介: android开发 加载so库的解析和出现的各种错误分析

一.android目前有几种cpu架构?

早期的Android系统几乎只支持ARMv5的CPU架构,你知道现在它支持多少种吗?7种!


Android系统目前支持以下七种不同的CPU架构:ARMv5,ARMv7 (从2010年起),x86 (从2011年起),MIPS (从2012年起),ARMv8,MIPS64和x86_64 (从2014年起),每一种都关联着一个相应的ABI。


二.每种cpu架构对应的文件夹名称是什么?

在Android系统上,每一个CPU架构对应一个ABI:armeabi,armeabi-v7a,x86,mips,arm64-v8a,mips64,x86_64


也就是说我们要想支持全部系统的手机需要放全所有不同版本的so库。


ARM架构属于RISC指令集,指令集精简、指令等长,虽然这样的设计可以提高处理效率,但在遇到复杂的指令后,就需要更多的简单指令来堆砌复杂任务;ARM从来只是设计低功耗处理器。其宗旨是设计低功耗处理器,这是他们的强项。


armeabi:ARM架构的默认选项,支持基于 ARM* v5TE 的设备,支持软浮点运算,但不支持硬件辅助浮点运算,支持所有的 ARM* 设备。


armeabi-v7a:armeabi-v7a 向下兼容,在兼容 armeabi 的基础上,支持基于 ARM* v7 的设备,支持硬件 FPU 指令,支持硬件浮点运算,目前大部分机器都属于armeabi-v7a。


arm64-v8a:arm64-v8a向下兼容 armeabi 和 armeabi-v7a,最主要的区别在于 arm64-v8a 支持64位,在 MIPS64 架构上增加了 ARMv7 架构中已经拥有的的TrustZone技术、虚拟化技术及NEON advanced SIMD技术等特性(ARM收购MIPS)。架构中包含两个执行状态:AArch32(也就是我们常说的ARMv7)和AArch64(ARMv8),也就是说64位的ARM处理器中同时包含着32位的ARMv7和64位的ARMv8两种架构,直接导致每种架构所拥有的晶体管减半。


X86构架是英特尔推出的一种复杂指令集,用于控制芯片的运行的程序,目前该构架的处理器已经广泛运用在PC领域,由于X86构架的处理器芯片在性能上比较强劲,善于执行复杂工作,所以当英特尔进军移动市场领域后(例如联想K800),就出现了X86的架构。X86构架属于典型的CISC,指令集丰富,指令不等长,善于执行复杂工作,更强调串行性能,它的整体运算能力要比只为移动而生的ARM架构强大,并且在PC领域已经广泛应用,拥有深厚的技术背景。英特尔设计超高性能的台式机和服务器处理器,并且的确做的不错。


x86:英特尔推出的32位CPU架构,生成的二进制代码可支持包含基于硬件的浮点运算的 IA-32 指令集,同时,x86机器基本上可以使用 intel 的 libhounini 项目直接在x86机器上运行仅含armeabi的动态库代码,也就会说x86机器对armeabi也能够兼容,不过性能上会有些损耗。


x86_64:英特尔推出的64位CPU架构,向下兼容x86。


mips和mips_64:MIPS是一种高性能的嵌入式CPU构架,其出发点是高性能,主要用于路由器、猫等


三.我们需要每种版本的so库都放全吗?

1.看你的so库的来源,是第三方提供的,还是自己开发的。倘若你是集成了某些第三方的sdk,然后他们提供了多少 ,你最好将它提供的都拷贝到项目中。(但是基本很少有能提供全面的so库支持的)


2.倘若是自己开发的 ,那就根据自己的情况,开发出对应版本的so库支持。


四.每种机型就只能加载一种适合自己版本的so库吗?

很多设备都支持多于一种的ABI。例如ARM64和x86设备也可以同时运行armeabi-v7a和armeabi的二进制包。但最好是针对特定平台提供相应平台的二进制包,这种情况下运行时就少了一个模拟层(例如x86设备上模拟arm的虚拟层),从而得到更好的性能(归功于最近的架构更新,例如硬件fpu,更多的寄存器,更好的向量化等)。


五.如何查看当前设备支持那些版本的so库?

我们可以通过Build.SUPPORTED_ABIS得到根据偏好排序的设备支持的ABI列表。但你不应该从你的应用程序中读取它,因为Android包管理器安装APK时,如果在对应的lib/ABI目录中存在.so文件的话,会自动选择APK包中为对应系统ABI预编译好的.so文件。


六.不同的开发环境so库应该放在哪里?

Android Studio工程放在jniLibs/ABI目录中(当然也可以通过在build.gradle文件中的设置jniLibs.srcDir属性自己指定)


Eclipse工程放在libs/ABI目录中(这也是ndk-build命令默认生成.so文件的目录)


AAR压缩包中位于jni/ABI目录中(.so文件会自动包含到引用AAR压缩包的APK中)


最终APK文件中的lib/ABI目录中


通过PackageManager安装后,在小于Android 5.0的系统中,.so文件位于app的nativeLibraryPath目录中;在大于等于Android 5.0的系统中,.so文件位于app的nativeLibraryRootDir/CPU_ARCH目录中。


七.为什么一般的项目中只看到armeabi文件夹?

因为所有的x86/x86_64/armeabi-v7a/arm64-v8a设备都支持armeabi架构的.so文件。


八.那我们是不是只放一种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 如下图:

 image.png

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

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实现!

所以看到这个错误,一般常见的几种情况分析。


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的不匹配,就会抛出这个异常了!


5 java.lang.UnsatisfiedLinkError:No implementation found for XXX

这种错误也是醉了,说是要建立跟c/cpp写的代码一样的包名和java文件


以上错误汇总来自于 http://blog.csdn.net/u013278099/article/details/50414438这篇文章


这个so库的错误是我这几天在做腾讯云视频直播的时候出现的一些问题,他们的sdk(1.8.2版本)里面的问题是:sdk里面提供的so库不全,导致出现各种问题。基本上面都介绍到了。


相关文章
|
2月前
|
移动开发 前端开发 Android开发
【02】建立各项目录和页面标准化产品-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
【02】建立各项目录和页面标准化产品-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
292 12
【02】建立各项目录和页面标准化产品-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
|
2月前
|
移动开发 JavaScript 应用服务中间件
【06】优化完善落地页样式内容-精度优化-vue加vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
【06】优化完善落地页样式内容-精度优化-vue加vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
247 5
【06】优化完善落地页样式内容-精度优化-vue加vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
|
2月前
|
移动开发 Rust JavaScript
【01】首页建立-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
【01】首页建立-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
592 4
【01】首页建立-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
|
3月前
|
开发工具 Android开发
X Android SDK file not found: adb.安卓开发常见问题-Android SDK 缺少 `adb`(Android Debug Bridge)-优雅草卓伊凡
X Android SDK file not found: adb.安卓开发常见问题-Android SDK 缺少 `adb`(Android Debug Bridge)-优雅草卓伊凡
525 11
X Android SDK file not found: adb.安卓开发常见问题-Android SDK 缺少 `adb`(Android Debug Bridge)-优雅草卓伊凡
|
2月前
|
移动开发 Android开发
【03】建立隐私关于等相关页面和内容-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
【03】建立隐私关于等相关页面和内容-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
150 0
|
3月前
|
Java 开发工具 Maven
【01】完整的安卓二次商业实战-详细的初级步骤同步项目和gradle配置以及开发思路-优雅草伊凡
【01】完整的安卓二次商业实战-详细的初级步骤同步项目和gradle配置以及开发思路-优雅草伊凡
221 6
|
5月前
|
移动开发 Java 编译器
Kotlin与Jetpack Compose:Android开发生态的演进与架构思考
本文从资深Android工程师视角深入分析Kotlin与Jetpack Compose在Android系统中的技术定位。Kotlin通过空安全、协程等特性解决了Java在移动开发中的痛点,成为Android官方首选语言。Jetpack Compose则引入声明式UI范式,通过重组机制实现高效UI更新。两者结合不仅提升开发效率,更为跨平台战略和现代架构模式提供技术基础,代表了Android开发生态的根本性演进。
198 0
|
5月前
|
安全 数据库 Android开发
在Android开发中实现两个Intent跳转及数据交换的方法
总结上述内容,在Android开发中,Intent不仅是活动跳转的桥梁,也是两个活动之间进行数据交换的媒介。运用Intent传递数据时需注意数据类型、传输大小限制以及安全性问题的处理,以确保应用的健壯性和安全性。
380 11
|
9月前
|
JavaScript Linux 网络安全
Termux安卓终端美化与开发实战:从下载到插件优化,小白也能玩转Linux
Termux是一款安卓平台上的开源终端模拟器,支持apt包管理、SSH连接及Python/Node.js/C++开发环境搭建,被誉为“手机上的Linux系统”。其特点包括零ROOT权限、跨平台开发和强大扩展性。本文详细介绍其安装准备、基础与高级环境配置、必备插件推荐、常见问题解决方法以及延伸学习资源,帮助用户充分利用Termux进行开发与学习。适用于Android 7+设备,原创内容转载请注明来源。
2174 77
|
6月前
|
安全 Java Android开发
为什么大厂要求安卓开发者掌握Kotlin和Jetpack?深度解析现代Android开发生态优雅草卓伊凡
为什么大厂要求安卓开发者掌握Kotlin和Jetpack?深度解析现代Android开发生态优雅草卓伊凡
282 0
为什么大厂要求安卓开发者掌握Kotlin和Jetpack?深度解析现代Android开发生态优雅草卓伊凡

推荐镜像

更多
  • DNS