Android 4.X 系统加载 so 失败的原因分析
1 so 加载过程
so 加载的过程可以参考小米的系统工程师的文章loadLibrary动态库加载过程分析
2 问题分析
2.1 问题
年前项目里新加了一个 so库,但发现native 方法的找不到的 crash
好多,好些都是报了java.lang.unsatisfiedlinkerror native method not found
,而且基本上是出现在4.x的系统里,特别是 4.4,4.2的系统。在网络上搜索相关的可能导致到这个问题的原因:
- so 文件没有在对应架构的目录里找到;
- 方法名有错误;
2.2 分析1
我们最开始是怀疑应用在安装时没有正确解压出对应的so
文件到相应目录,因此加了相应统计来看发生crash
的手机是否是因为找不到对应的 so
文件导致的;但统计数据发现这些手机里都可以找到对应架构的 so
文件,因此就排除了不存在so
文件导致的 crash
;
2.3 分析2
我们同事以前有发现在 Android 4.x
系统里,如果so
文件是在应用启动时加载的,但使用时机却在后面的时间点,so
加载进手机的内存可能会被系统由于资源紧张而回收掉,这种情况下,可以通过重新加载一次 so
文件来减少相关的 crash
,这种方法 fix
了某个量很高的 so 相关的crash
。但我们的 so
的 crash
明显是不属于这种情况的,因为我们是通过 System.load()
方法加载完 so
文件后,就调用相关的方法,这时内存肯定是还在的。在分析了一系列可能的原因后,怀疑这个crash
是因为应用安装时解压出来的 so
文件是损坏的,因此我们尝试在第一次发生这个crash
时,将这个crash
catch
住,然后在 catch
块将原来目录下的 so
文件删除掉,并重新从应用的安装目录解压出对应的so
文件放到原来的目录,并加了相关的统计来验证。so
的加载用了 Relinkder。相关的简化版本代码如下:
relinker.loadLibrary(getApplicationContext(), "so_name");
try{
// call native method
} catch(UnsatisfiedLinkError e) {
//some stats
String library = "so_name";
String libName = System.mapLibraryName(library);
File workaroundLibDir = getApplicationContext().getDir("lib", Context.MODE_PRIVATE);
File workaroundLibFile = new File(workaroundLibDir, libName);
workaroundLibFile.delete();
apkLibraryInstaller.installLibrary(
getApplicationContext()
, supportedAbis()
, libName
, workaroundLibFile
, relinker
);
System.load(workaroundLibFile.getAbsolutePath());
//call native method
// some stats
}
2.4 分析3
在使用的 2.3 的解决方法后,我们的 so
的 java.lang.unsatisfiedlinkerror native method not found
大部分消失了。理论上使用过一次重新解压so
文件后,这个用户在下一次升级前都应该不会再发生了类似的 crash
了,但我们的统计数据发现,有些用户每一次启动都需要进入catch
块来避免crash
,而每次都可以通过 reload
来正常使用我们的应用,这至今还是个迷,还没有想明白是什么情况会导致这个问题?手机的存储有问题?但其他的so
又没有这个问题。希望如果有同行解决过类似的问题的,指点一下。
3 总结
Android 4.X 系统加载 so 后,出现 java.lang.unsatisfiedlinkerror native method not found
的crash
的原因除了网上所说的 不存在这个so 和 方法名有问题(商用的应用应该不会有这个问题的)外,还有两个原因:
- so 加载进系统的内存被系统由于资紧张而回收了,这种情况下直接再
load
一下so
文件就可以解决大部分; - so 文件有问题,这种情况下,可以通过重新从应用安装目录解压出对应的
so
文件并重新加载来解决大部分;
这两种方法不能保证可以100%解决问题,但可以减少大部分问题(90%);
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】