引用: https://blog.csdn.net/ouyang_peng/article/details/51168072java
今天测试人员测试集成版本时除了一个bug:关于华为 Mate 8手机Android 6.0系统运行刚刚提测的版本时,出现闪退的bug,而小米 4 手机Android 6.0系统却没有出现任何bug,运行良好。后来查看本人相关模块的代码,发现本人集成版本相关模块的代码和分支版本相关模块的代码是如出一辙的,那就是说本人把分支代码合并到主干代码是没有问题的,因此去查看主干代码的问题。android
通过一番查看提交日志,发现有位同事再我合并代码以前,提交了一个关于友盟推送的so文件的记录,原来他加入了一个arm64-v8a文件夹,里面有友盟推送的arm64-v8a的so库文件。而其余的so库文本却没有arm64-v8a对应的版本。web
经过百度查到知乎有一段关于arm64-v8a的解释:微信
arm64-v8a是能够向下兼容的,但前提是你的项目里面没有arm64-v8a的文件夹,若是你有两个文件夹armeabi和arm64-v8a,两个文件夹,armeabi里面有a.so 和 b.so,arm64-v8a里面只有a.so,那么arm64-v8a的手机在用到b的时候发现有arm64-v8a的文件夹,发现里面没有b.so,就报错了,因此这个时候删掉arm64-v8a文件夹,这个时候手机发现没有适配arm64-v8a,就会直接去找armeabi的so库,因此要么你别加arm64-v8a,要么armeabi里面有的so库,arm64-v8a里面也必须有架构
做者:green jim
连接:微信的安装包在只编译了armeabi,没有x86,arm64-v8a是如何运行在各类处理器的手机上的? - green jim 的回答
来源:知乎
著做权归做者全部。商业转载请联系做者得到受权,非商业转载请注明出处。app
发现原来华为 Mate 8手机是64位的操做系统,而小米 4 手机是32位的操做系统,因此小米 4 手机手机运行APP没bug,而华为 Mate 8手机运行APP出现闪退bug。框架
从截图能够看出来,第一个项目中有 arm64-v8a,而没有x86目录,第二个项目中没有arm64-v8a,而有x86目录。第一个项目是做为项目引用导入到第二个项目中的。函数
从截图能够看出来,第一个项目中和第二个项目中没有的libs目录下,都是armeabi-v7a、armeabi、x86三个目录,保持一致。第一个项目是做为项目引用导入到第二个项目中的。性能
解决方法是:从友盟官方中去下载x86的相关so文件,放在x86目录下,把arm64-v8a目录删除。将全部关于so文件的都要保持一致,即:若是你要添加一个armeabi-v8a目录,下面放第三方的armeabi-v8a相关的so文件,那么你其余的so文件都要有相应想armeabi-v8a版本,否则就会报错。测试
来自于博客:《与 .so 有关的一个终年大坑 》给的建议是:
- 为了减少 apk 体积,只保留 armeabi 和 armeabi-v7a 两个文件夹,并保证这两个文件夹中 .so 数量一致
- 对只提供 armeabi 版本的第三方 .so,原样复制一份到 armeabi-v7a 文件夹
下面文章转载于asce1885(简书做者):关于Android的.so文件你所须要知道的
(原文连接:关于Android的.so文件你所须要知道的)
著做权归做者全部,转载请联系做者得到受权,并标注“简书做者”。
早期的Android系统几乎只支持ARMv5的CPU架构,你知道如今它支持多少种吗?7种!
Android系统目前支持如下七种不一样的CPU架构:ARMv5,ARMv7 (从2010年起),x86 (从2011年起),MIPS (从2012年起),ARMv8,MIPS64和x86_64 (从2014年起),每一种都关联着一个相应的ABI。
应用程序二进制接口(Application Binary Interface)定义了二进制文件(尤为是.so文件)如何运行在相应的系统平台上,从使用的指令集,内存对齐到可用的系统函数库。在Android系统上,每个CPU架构对应一个ABI:armeabi,armeabi-v7a,x86,mips,arm64-v8a,mips64,x86_64。
若是项目中使用到了NDK,它将会生成.so文件,所以显然你已经在关注它了。若是只是使用Java语言进行编码,你可能在想不须要关注.so文件了吧,由于Java是跨平台的。但事实上,即便你在项目中只是使用Java语言,不少状况下,你可能并无意识到项目中依赖的函数库或者引擎库里面已经嵌入了.so文件,并依赖于不一样的ABI。
例如,项目中使用RenderScript支持库,OpenCV,Unity,android-gif-drawable,SQLCipher等,你都已经在生成的APK文件中包含.so文件了,而你须要关注.so文件。
Android应用支持的ABI取决于APK中位于lib/ABI目录中的.so文件,其中ABI多是上面说过的七种ABI中的一种。
Native Libs Monitor这个应用能够帮助咱们理解手机上安装的APK用到了哪些.so文件,以及.so文件来源于哪些函数库或者框架。
固然,咱们也能够本身对app反编译来获取这些信息,不过相对麻烦一些。
不少设备都支持多于一种的ABI。例如ARM64和x86设备也能够同时运行armeabi-v7a和armeabi的二进制包。但最好是针对特定平台提供相应平台的二进制包,这种状况下运行时就少了一个模拟层(例如x86设备上模拟arm的虚拟层),从而获得更好的性能(归功于最近的架构更新,例如硬件fpu,更多的寄存器,更好的向量化等)。
咱们能够经过Build.SUPPORTED_ABIS获得根据偏好排序的设备支持的ABI列表。但你不该该从你的应用程序中读取它,由于Android包管理器安装APK时,会自动选择APK包中为对应系统ABI预编译好的.so文件,若是在对应的lib/ABI目录中存在.so文件的话。
处理.so文件时有一条简单却并不知名的重要法则。
你应该尽量的提供专为每一个ABI优化过的.so文件,但要么所有支持,要么都不支持:你不该该混合着使用。你应该为每一个ABI目录提供对应的.so文件。
当一个应用安装在设备上,只有该设备支持的CPU架构对应的.so文件会被安装。在x86设备上,libs/x86目录中若是存在.so文件的话,会被安装,若是不存在,则会选择armeabi-v7a中的.so文件,若是也不存在,则选择armeabi目录中的.so文件(由于x86设备也支持armeabi-v7a和armeabi)。
当你引入一个.so文件时,不止影响到CPU架构。我从其余开发者那里能够看到一系列常见的错误,其中最多的是”UnsatisfiedLinkError”,”dlopen: failed”以及其余类型的crash或者低下的性能:
使用NDK时,你可能会倾向于使用最新的编译平台,但事实上这是错误的,由于NDK平台不是后向兼容的,而是前向兼容的。推荐使用app的minSdkVersion对应的编译平台。
这也意味着当你引入一个预编译好的.so文件时,你须要检查它被编译所用的平台版本。
.so文件能够依赖于不一样的C++运行时,静态编译或者动态加载。混合使用不一样版本的C++运行时可能致使不少奇怪的crash,是应该避免的。做为一个经验法则,当只有一个.so文件时,静态编译C++运行时是没问题的,不然当存在多个.so文件时,应该让全部的.so文件都动态连接相同的C++运行时。
这意味着当引入一个新的预编译.so文件,并且项目中还存在其余的.so文件时,咱们须要首先确认新引入的.so文件使用的C++运行时是否和已经存在的.so文件一致。
这一点在前文已经说到了,但你应该真的特别注意它,由于它可能发生在根本没有意识到的状况下。
例如:你的app支持armeabi-v7a和x86架构,而后使用Android Studio新增了一个函数库依赖,这个函数库包含.so文件并支持更多的CPU架构,例如新增android-gif-drawable函数库:
发布咱们的app后,会发现它在某些设备上会发生Crash,例如Galaxy S6,最终能够发现只有64位目录下的.so文件被安装进手机。
解决方案:从新编译咱们的.so文件使其支持缺失的ABIs,或者设置
显示指定支持的ABIs。
最后一点:若是你是一个SDK提供者,但提供的函数库不支持全部的ABIs,那你将会搞砸你的用户,由于他们能支持的ABIs必将只能少于你提供的。
咱们每每很容易对.so文件应该放在或者生成到哪里感到困惑,下面是一个总结:
全部的x86/x86_64/armeabi-v7a/arm64-v8a设备都支持armeabi架构的.so文件,所以彷佛移除其余ABIs的.so文件是一个减小APK大小的好技巧。但事实上并非:这不仅影响到函数库的性能和兼容性。
x86设备可以很好的运行ARM类型函数库,但并不保证100%不发生crash,特别是对旧设备。64位设备(arm64-v8a, x86_64, mips64)可以运行32位的函数库,可是以32位模式运行,在64位平台上运行32位版本的ART和Android组件,将丢失专为64位优化过的性能(ART,webview,media等等)。
以减小APK包大小为由是一个错误的借口,由于你也能够选择在应用市场上传指定ABI版本的APK,生成不一样ABI版本的APK能够在build.gradle中以下配置: