加载so异常总结:System.loadLibrary

安卓开发中可能会遇到加载so的场景,但可能会遇到加载异常的情况。笔者对自己遇到的此类情况稍作总结。

问题背景

有一段网络请求的业务代码原本是在一个应用中的,为了实现复用,将这段业务代码封装成一个模块(module),然后编译成aar给另一个应用使用。但结果发现,原应用中这段业务代码是正常的,但是移植到另一个应用就出现了异常。

分析思路

分析此类问题的思路就是重点考察差异点。因为业务代码是相同的,但是在其中一个应用正常,在另一个应用异常,则需要考虑两个应用的差异点。最初考虑到的差异点或者可能的原因有:

  • 包名:两个应用,最基本的不同就是包名的不同。它的不同可能会带来异常。
  • 签名:不同的应用可能使用不同的签名,签名可能会引起业务认证或者鉴权不通过。
  • 权限:应用不同,拥有的权限也不同
  • 其他方面:其他未考虑到的差异点。

最初的思路即为这几个点。在分析问题时可以暂时确认这几个方向。若没有更为准确的思路或者灵感,最靠谱的手段还是查看日志。

分析问题最基本的手段:查看日志

尽管考虑了多个差异点,分析了可能的原因。但最实在的方式还是查看异常日志,进而为定位问题缩小范围。通过日志,定位到异常日志为:

dlopen failed: library "xx.so" needed or dlopened by "/system/lib64/libnativeloader.so" is not accessible for the namespace "classloader-namespace"

发现是加载so异常导致的网络请求异常。

在查看日志方面,笔者有一个小技巧,就是如果报异常或错误的代码是自己工程中的,或者工程中的代码可以捕获异常或错误,可以将这些异常或错误改写成对应的基类,并将其对象的信息打印出来。

例如,笔者工程里此处代码的错误类型为:

catch(UnsatisfiedLinkError e){
    Log.e(TAG,"Load faild.");
}

对其修改,可变为:

catch(Error e){
    Log.e(TAG,"Load faild." + e.getMessage());
    Log.e(TAG,"Load faild." + e.getCause());
}

改为基类后,可以避免其他异常或错误被漏掉,并且可以将错误或异常信息打印出来。

加载so异常分析

从前面的日志可以看出,是加载so的异常。但该异常似乎与包名、签名等关系不大。通过查阅相关材料,发现可能是权限的问题,即无法加载到制定的so。若无法获取权限,可以将目标so添加进白名单,让其变成公有的。

在下面的几个目录中,可能都存在public.libraries.txt文件,这个文件中的so表示是公有的。任何应用都可以加载。

/etc/public.libraries.txt
/system/etc/public.libraries.txt
/vendor/etc/public.libraries.txt

这些不同的文件,对应了不同路径下的so。
使用adb remout后,可以将其pull出来,将需要加载的so添加到文件的末尾,再push回去。

部分网友的办法是将该so取出来,放到工程中,也能解决无法访问的问题。

修改以后,发现打印的错误变了。实际上,如果不像上文中介绍的那样将代码中的错误类型改成基类,这里随着错误类型的更改,可能都无法查看到具体的错误日志,但是业务还是异常。所以建议最好先将catch中的错误或异常修改成基类。

混淆导致so无法加载

由于错误日志变更,查看其内容发现,so注册失败:

Faild to register native method xxx

到了这一步,也可以得知可能不是签名或包名的问题,因为最初的注册都不成功。
仔细观察日志,发现其中有被混淆的代码,为此查看原应用中此部分代码,发现此模块的代码都没有混淆。只有另一个应用对整体使用了混淆。

但是心中不免有疑虑,编译的aar又没有混淆,放到新的应用中,也能被混淆吗?
怀着试一试的态度,将新应用中的混淆关闭。最后发现业务代码居然正常了。

为此可以总结得到如下结论:
就算模块编译的aar没有被混淆,但是被放到另一个应用中,如果不添加例外,那么aar中的代码依然可能被混淆,进而让so加载时,找不到对应方法,进而失败。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 1、通过CocoaPods安装项目名称项目信息 AFNetworking网络请求组件 FMDB本地数据库组件 SD...
    阳明AI阅读 16,124评论 3 119
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 136,326评论 19 139
  • day1到day2好像相隔了很久。。。没事,还是有了day2了 之前一直都是做活动页,基本上没有接触到数据接口这些...
    qqqc阅读 363评论 0 0
  • 一、缘由 近日精力管理小组拆书,本周由我进行这本书第五章的解读,通过对这本书前面内容的阅读和学习,我把自己关于学习...
    清心若莲12阅读 5,940评论 0 1

友情链接更多精彩内容