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。但我们的 socrash 明显是不属于这种情况的,因为我们是通过 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 的解决方法后,我们的 sojava.lang.unsatisfiedlinkerror native method not found 大部分消失了。理论上使用过一次重新解压so 文件后,这个用户在下一次升级前都应该不会再发生了类似的 crash了,但我们的统计数据发现,有些用户每一次启动都需要进入catch块来避免crash,而每次都可以通过 reload来正常使用我们的应用,这至今还是个迷,还没有想明白是什么情况会导致这个问题?手机的存储有问题?但其他的so又没有这个问题。希望如果有同行解决过类似的问题的,指点一下。

3 总结

Android 4.X 系统加载 so 后,出现 java.lang.unsatisfiedlinkerror native method not foundcrash的原因除了网上所说的 不存在这个so 和 方法名有问题(商用的应用应该不会有这个问题的)外,还有两个原因:

  • so 加载进系统的内存被系统由于资紧张而回收了,这种情况下直接再load一下 so 文件就可以解决大部分;
  • so 文件有问题,这种情况下,可以通过重新从应用安装目录解压出对应的 so 文件并重新加载来解决大部分;

这两种方法不能保证可以100%解决问题,但可以减少大部分问题(90%);

Android 4.X 系统加载 so 失败的原因分析的更多相关文章

  1. React Native 断点调试 跨域资源加载出错问题的原因分析

    写在前面 ————如果从头开始看还没解决,试试文章最后的绝招 闲来无事,折腾了一下React Native,相比之前,开发体验好了不少.但在真机断点调试那里遇到了跨域资源加载出错的问题,一番探索总算解 ...

  2. H5:加载原理,慢加载和卡顿原因分析,

    前端H5工作原理: 请求和显示原理 H5页面卡顿原因分析: 1.动画太多:渲染重绘占用GPU 2.页面操作导致重绘频繁 3.页面元素复杂:资源类标签太多(图像/视频/dom树太长) 4.内置webvi ...

  3. RequireJS首次加载偶尔失败

    现象:第一次加载JS文件,首次加载偶尔失败: 原因:require(['jquery', 'operamasks', 'zTree', 'jQueryCookie'],中前后引用同步加载: 解决方式: ...

  4. Android系统加载Apk文件的时机和流程分析(1)--Android 4.4.4 r1的源码

    本文博客地址:https://blog.csdn.net/QQ1084283172/article/details/80982869 Android系统在启动时安装应用程序的过程,这些应用程序安装好之 ...

  5. Android 的 so 文件加载机制

    本篇文章已授权微信公众号 guolin_blog (郭霖)独家发布 最近碰到一些 so 文件问题,顺便将相关知识点梳理一下. 提问 本文的结论是跟着 System.loadlibrary() 一层层源 ...

  6. Android中一张图片加载后所占用内存大小的获取与测试

    Android程序中一旦加载的图片比较多,就有可能出现Out of Memory而导致程序崩溃.这个一方面是因为Android系统本身对于每个单独的进程有内存大小的限制(有16M,64M,128M,2 ...

  7. Android中的动态加载机制

    在目前的软硬件环境下,Native App与Web App在用户体验上有着明显的优势,但在实际项目中有些会因为业务的频繁变更而频繁的升级客户端,造成较差的用户体验,而这也恰恰是Web App的优势.本 ...

  8. java攻城狮之路(Android篇)--widget_webview_metadata_popupwindow_tabhost_分页加载数据_菜单

    一.widget:桌面小控件1 写一个类extends AppWidgetProvider 2 在清单文件件中注册: <receiver android:name=".ExampleA ...

  9. Android中的Glide加载图片

    注意:在Android Studio的项目的build.gradle中添加: compile 'com.github.bumptech.glide:glide:3.6.1' 然后同步一下 目录: 使用 ...

随机推荐

  1. C#LeetCode刷题之#374-猜数字大小(Guess Number Higher or Lower)

    问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/3993 访问. 我们正在玩一个猜数字游戏. 游戏规则如下: 我从 ...

  2. C#LeetCode刷题之#350-两个数组的交集 II(Intersection of Two Arrays II)

    问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/4044 访问. 给定两个数组,编写一个函数来计算它们的交集. 输入 ...

  3. Android 开发学习进程0.16 layout_weight属性 R文件关联XML Module

    layout_weight属性 layout_weight属性我们常常用到,但有时候会发现它还有一些奇怪的属性,比如大多数使用时会把宽度设置成0,但要是宽度不设置成0会有什么效果? layout_we ...

  4. west_wild 靶机

    ways:smb枚举+suid提权 1:扫描主机发现IP 老套路:netdiscover 一波 2:nmap扫描,发现开放的 端口很多并且开放是SMB协议 3:对目录扫描,发现没有可以利用的点 4:从 ...

  5. OpenJDK和OracleJDK的区别

    在2006年11月13日的JavaOne大会上,Sun公司(当时还没被收购)宣布计划要把Java开源,在随后的一年多时间内,它陆续地将JDK的各个部分在GPL v2(GNU General Publi ...

  6. Dbeaver连接Hive和Mysql的配置

    1.连接Hive 首选需要配置Hive 这里我们采用的是JDBC的连接方式 (1) 在Hive中后台启动hiveserver2 [root@hadoop-101 hive]# bin/hiveserv ...

  7. 无法将“vue”项识别为 cmdlet、函数、脚本文件或可运行程序的名称

    状况 如果在使用 vue 初始化项目的时候提示: vue : 无法将“vue”项识别为 cmdlet.函数.脚本文件或可运行程序的名称.请检查名称的拼写,如果包括路径,请确保路径正确,然后再试一次. ...

  8. nvm -- node 多版本管理器

    Node.js 越来越热,应用的场景也越来越多. 在开发中,我们可能同时在进行多个 node 项目,而这些不同的项目所使用的 node 版本又是不一样的,或者是要用更新的 node 版本进行试验和学习 ...

  9. 手把手教Linux驱动1-模块化编程,玩转module

    大家好,从本篇起,一口君将手把手教大家如何来学习Linux驱动,预计会有20篇关于驱动初级部分知识点.本专题会一直更新,有任何疑问,可以留言或者加我微信. 一.什么是模块化编程? Linux的开发者, ...

  10. Vue最全知识点

    声明:本篇文章纯属笔记性文章,非整体原创,是对vue知识的整理, 基础篇 说说你对MVVM的理解 Model-View-ViewModel的缩写,Model代表数据模型,View代表UI组件,View ...