What you should know about .so files
In its early days, the Android OS was pretty much supporting only one CPU architecture: ARMv5.
Do you know how many it does support now? … 7!
Seven distinct CPU-architectures are currently supported by the Android OS: ARMv5, ARMv7 (since 2010), x86 (2011), MIPS (2012), ARMv8, MIPS64 and x86_64 (2014). Each of them is associated with a respective ABI.
An Application Binary Interface is the definition of how binaries (esp. .so files) should be made in order to work on the platform, from the instruction set used and memory alignment, to the system libraries that are available. On Android there is one per CPU architecture: armeabi, armeabi-v7a, x86, mips, arm64-v8a, mips64, x86_64.
Why should you care about .so files in the first place?
If you’re using the NDK, you’re generating .so files, so you obviously already care. If you’re dealing only with Java code, you could think you don’t need to, as it’s cross-platform… but in fact, even in this case, quite often, you may rely without knowing it on libraries and engines that make your app embed .so files and become ABI-dependent/
Using the RenderScript support Library? OpenCV? Unity? android-gif-drawable? SQLCipher? You’ve got .so files inside your APK, and you need to care about these.
The ABIs supported by your Android application are determined by the presence of .so files inside your APK, under the “lib/<ABI>” folders where ABI can be one or more of armeabi, armeabi-v7a, arm64-v8a, mips, mips64, x86, x86_64 (the current seven ABIs).
Native Libs Monitor can help you understanding what .so files are embedded inside your APK and installed on your device, and which libraries and frameworks they’re coming from.
Most devices are compatible with more than one ABI. For example, ARM64 devices and x86 devices can run armeabi-v7a and armeabi binaries too! But it’s always better to provide libraries compiled for the preferred ABI of the device. This way, libraries can run without an emulation layer (in case of arm libs on x86 devices), and get more performance thanks to the recent architecture improvements (hardware fpu, more registers, better vectorization, etc).
You can get the list of supported ABIs, sorted by preference, from Build.SUPPORTED_ABIS. But you shouldn’t need to read it from your app, as Android’s package manager will automatically install the .so files compiled for your device preferred ABI that are present inside your APK, if they’re properly present under lib/<ABI>.
That’s where things may go wrong for your app!
There is a dead simple but not well-known important rule to follow when dealing with .so files.
You should provide libraries optimized for each ABIs if possible, but it’s all in or nothing: you shall not mix. You have to provide the full set of the libraries you’re using in each ABI folder.
When an application is installed on a device, only the .so files from one of its supported architectures are getting installed. On x86 devices, that can be the libs from the x86 folder if there is one, else from the armeabi-v7a, else armeabi folder (yes, x86 devices support these too).
But they may go wrong in many other ways too…
When you include a .so file, not only the architecture matters. Here is a list of really common mistakes I see from other developers, that are leading to “UnsatisfiedLinkError”, “dlopen: failed”, and other crashes or bad performance:
using a .so file that has been compiled against android-21+ platform version, to run it on android-15 device. Ouch.
When using the NDK, you may be tempted to “compile against the latest platform”, but it’s in fact quite wrong as ndk platforms aren’t backward compatible, they’re forward compatible! Use the same platform level than your app’s minSdkVersion.
That means that when you’re including a .so file that has already been compiled, you have to check the version it has been made to run on.
mixing .so files that are using different C++ runtimes
.so files can rely on various C++ runtimes, statically compiled or dynamically loaded. Mixing versions of C++ runtimes can lead to many weird crashes and should be avoided. As a rule of thumb, when having only one .so file, it’s ok to statically compile a C++ runtime, else you should have them all dynamically linking the same C++ runtime.
That means that when you’re including a .so file that has already been compiled and you already have some of them, you have to check the C++ runtime it’s using.
not providing all the libs for each of the supported platforms
This was already previously described, but you should really pay attention to this, as it may happen behind your back.
Example: You have an Android app with .so files for armeabi-v7a and x86 architectures. Then you add a dependency on another library that embeds .so files and supports more architectures, as android-gif-drawable: compile ‘pl.droidsonroids.gif:android-gif-drawable:1.1.+’.
Release your app, and then you’ll see it crashing on some devices, like the Galaxy S6, because only the .so files from the 64-bit directory got installed.
Solution: recompile your libs to support the missing ABIs, or set ndk.abiFilters to the one you support.
One more thing: If you’re a library provider, and you’re not supporting all the ABIs, you’re screwing up your customers, as they can’t support more ABIs than you do.
putting .so files in the wrong place
It’s easy to get confused on where .so files should be put or generated by default, here is a summary:
- jniLibs/ABI inside an Android Studio project (can be changed using jniLibs.srcDir property)
- libs/ABI inside an eclipse project (that’s where ndk-build generates libs by default too)
- jni/ABI inside an AAR (the libs will get automatically included in the APK that references the AAR).
- lib/ABI inside the final APK
- inside the app’s nativeLibraryPath on a <5.0 device / nativeLibraryRootDir/CPU_ARCH on a >=5.0 device (done by PackageManager during app installation)
providing only armeabi libs and ignoring all the other ABIs
armeabi is supported by all the x86/x86_64/armeabi-v7a/arm64-v8a devices, so that may look like a good trick to remove all the other ABIs to generate a light APK. But it’s not: there is an impact on performance and compatibility, and not only for the library itself.
x86 devices can run ARM libraries quite well, but it’s not 100% crash proof, particularly on the older devices. 64-bit devices (arm64-v8a, x86_64, mips64) can all run 32-bit libraries, but they do so in 32-bit mode, running a 32-bit version of ART and Android components, loosing the 64-bit performance improvements that have been made on the 64-bit version of ART, webview, media…
Reducing APK’s weight is in any case a false excuse, as you can upload distinct ABI-dependent APKs to the Play Store (for the same app entry, of course). You only have to switch to advanced mode and upload your APKs with different ABI support and versionCodes. Generating these APKs is as simple as adding this to your build.gradle:
Java
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
android {
...
splits {
abi {
enable true
reset()
include 'x86', 'x86_64', 'armeabi-v7a', 'arm64-v8a' //select ABIs to build APKs for
universalApk true //generate an additional APK that contains all the ABIs
}
}
// map for the version code
project.ext.versionCodes = ['armeabi': 1, 'armeabi-v7a': 2, 'arm64-v8a': 3, 'mips': 5, 'mips64': 6, 'x86': 8, 'x86_64': 9]
android.applicationVariants.all { variant ->
// assign different version code for each output
variant.outputs.each { output ->
output.versionCodeOverride =
project.ext.versionCodes.get(output.getFilter(com.android.build.OutputFile.ABI), 0) * 1000000 + android.defaultConfig.versionCode
}
}
}
|
Using private system libraries
The libraries you can use are the ones which are part of the NDK ones. Any other lib isn’t guaranteed to work across devices and may trigger crashes starting with Android N: https://developer.android.com/preview/behavior-changes.html#ndk
TL;DR:
meme
What you should know about .so files的更多相关文章
- Conversion to Dalvik format failed: Unable to execute dex: Multiple dex files define ...
Conversion to Dalvik format failed: Unable to execute dex: Multiple dex files define ... 这个错误是因为有两个相 ...
- The type javax.ws.rs.core.MediaType cannot be resolved. It is indirectly referenced from required .class files
看到了http://stackoverflow.com/questions/5547162/eclipse-error-indirectly-referenced-from-required-clas ...
- 未能写入输出文件“c:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\root\106f9ae8\cc0e1
在本地开发环境没问题,但是发布到服务器出现:未能写入输出文件"c:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.Ne ...
- Find and delete duplicate files
作用:查找指定目录(一个或多个)及子目录下的所有重复文件,分组列出,并可手动选择或自动随机删除多余重复文件,每组重复文件仅保留一份.(支持文件名有空格,例如:"file name" ...
- Android Duplicate files copied in APK
今天调试 Android 应用遇到这么个问题: Duplicate files copied in APK META-INF/DEPENDENCIES File 1: httpmime-4.3.2.j ...
- Oracle客户端工具出现“Cannot access NLS data files or invalid environment specified”错误的解决办法
Oracle客户端工具出现"Cannot access NLS data files or invalid environment specified"错误的解决办法 方法一:参考 ...
- files list file for package 'xxx' is missing final newline
#!/usr/bin/python # 8th November, 2009 # update manager failed, giving me the error: # 'files list f ...
- Mac osx 安装PIL出现Some externally hosted files were ignored (use --allow-external PIL to allow).
出现这个问题Some externally hosted files were ignored (use --allow-external PIL to allow)的主要原因是PIL的一些依赖库还没 ...
- 【Linux】Too many open files
ZA 的BOSS 最近出现Too many open files 异常,这个异常一般是由于打开文件数过多引起, 最常见原因是某些连接一致未关闭 记录一些排查用到的指令 查看每个用户最大允许打开文件数量 ...
- [转]html5表单上传控件Files API
表单上传控件:<input type="file" />(IE9及以下不支持下面这些功能,其它浏览器最新版本均已支持.) 1.允许上传文件数量 允许选择多个文件:< ...
随机推荐
- win10专业版激活方法
slmgr.vbs /upk 此时弹出窗口显未“已成功卸载了产品密钥”. slmgr /ipk W269N-WFGWX-YVC9B-4J6C9-T83GX 弹出窗口提示:“成功的安装了产品密钥”. s ...
- js 模拟鼠标事件
<!DOCTYPE html> <html> <head lang="zh-CN"> <meta charset="UTF-8& ...
- 垃圾回收机制GC知识再总结兼谈如何用好GC(其他信息: 内存不足)
来源 图像操作,易内存泄露,边界像素 一.为什么需要GC 应用程序对资源操作,通常简单分为以下几个步骤: 1.为对应的资源分配内存 2.初始化内存 3.使用资源 4.清理资源 5.释放内存 应用程序对 ...
- MATLAB:保存mat文件
X_Y_pred_00_0000.mat里存有三个mat文件: 另存:
- 腾讯爱玩某处csrf导致骚扰用户(QQ弹窗+QQ会话+微博)
点击提醒,然后抓包: POST /dyid_proc.php HTTP/1.1 Host: tx.qq.com User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW ...
- Thinkphp5 iis环境下安装报错400 500
要求一:服务器需要开启伪静态功能 要求二:新建文件夹web.config 放到入口目录下(如public/web.config 或者/web.config),内容如: <?xml versio ...
- Oauth2.0(二):开放平台
上一节说到Oauth2.0 的交互模型.模型涉及到三方:资源拥有者.客户端.服务提供方.其中,服务提供方包含两个角色:鉴权服务器和资源服务器.鉴权服务器负责对用户进行认证,并授权给客户端权限.认证这一 ...
- c#直接调用ssis包实现Sql Server的数据导入功能
调用ssis包实现Sql Server的数据导入功能网上已经有很多人讨论过,自己参考后也动手实现了一下,上一次笔者的项目中还用了一下这个功能.思前想后,决定还是贴一下增强记忆,高手请54. 1.直接调 ...
- Centos6.3 下使用 Tomcat-6.0.43 非root用户 jsvc模式部署 生产环境 端口80 vsftp
一.安装JDK环境 方法一. 官方下载链接 http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260 ...
- ios开发之--textview意见反馈页面(占位label,字数统计,提交按钮的交互设置)
记录一个页面的功能: textview的占位符,字数统计,提交按钮的交互设置,具体效果图如下: