Relinker源码分析

作为源码分析的第一篇文章,我们先从一个相对简单的开源库开始:Relinker(点击看源码链接)。这库由来已久了,github也有1000+的star。我在工作中虽然有用到这个库,却一直没仔细看过源码,今天我们就来分析一下。

开始之前先来讲讲背景。

开发中我们常常会遇到这样的异常:java.lang.UnsatisfiedLinkError: Couldn’t load xxxx from loader dalvik.system.PathClassLoader。我们都知道这表示App没有找到对应的so。

有一种情况,为了减小包体积,我们通常只保留arm架构的so,而删除x86、mips等平台的so。这样就导致有些手机上会报找不到so的情况。这样的问题我们可以通过查看手机的CPU架构来辨别。而对于arm架构的手机,也会存在找不到so的情况。这又是因为什么原因呢?

从网上找到的一些文章来看,找不到so的一部分原因可能是由于PackageManager安装包的时候出错了。Relinker就是为了处理这种情况。它的整体思路其实很简单,先尝试使用系统原生方式去加载so,如果加载失败,Relinker会尝试从apk中拷贝so到App沙箱目录下,然后再去尝试加载so。最终,我们可以使用 ReLinker.loadLibrary(context, “mylibrary”) 来代替原生的加载方式System.loadLibrary(“mylibrary”)

下面就来具体分析一下Relinker的代码。

Relinker库的代码结构如下图(确实非常简单~~)
在这里插入图片描述

主要的功能都是在下面的几个类里。

ReLinker:调用的入口,其中还包含几个接口的定义。
ReLinkerInstance:自定义的so的加载逻辑都在这个类中。
SystemLibraryLoader:封装了系统so的加载方式,默认都是先调用这个类去加载so。
ApkLibraryInstaller:主要是提取Apk中so的一些逻辑。

而elf目录下的文件的作用是分析so文件,这里我们不去做过多的分析。

先从ReLinker的入口loadLibrary开始。它其实只是创建了一个ReLinkerInstance的实例,并调用了ReLinkerInstance的loadLibrary方法。
在这里插入图片描述

ReLinkerInstance的构造方法中会传入两个参数,一个是系统的so加载器 SystemLibraryLoader,一个是apk中so的提取类 ApkLibraryInstaller。
在这里插入图片描述

loadLibrary最终会调用到 loadLibraryInternal() 方法,这个方法包含了so加载的主要逻辑。这个类主要有两个作用,首先调用了SystemLibraryLoader去加载so,如果成功就直接返回;如果失败,需要调用ApkLibraryInstaller的installLibrary方法来提取so。这里通过跟踪getWorkaroundLibFile方法,我们可以看到,提取的so文件最终存放的目录为App沙箱目录的lib子目录。
在这里插入图片描述

接着往下看,如果recursive为true,会调用ElfParser类来分析所加载的so文件,检查是否有依赖的so文件需要加载。如果有的话就递归的去加载对应的so文件。
在这里插入图片描述

关于ElfParser的具体逻辑就不去详细分析了,看到这里我们知道主要功能就在ApkLibraryInstaller的installLibrary方法中,我们继续来看这个方法。installLibrary方法先调用findAPKWithLibrary来找到此App完整apk文件的目录,然后通过ZipFile来解析得到so文件的访问入口。我们看到sourceDirectories方法在Android L以上版本会通过splitSourceDirs来获得额外的一个路径。关于这个逻辑,对我们来讲意义不是很大,但我觉得有必要讲一下。split apks是Android 5.0开始提供的多apk构建机制,借助split apks可以将一个apk基于ABI和屏幕密度两个维度拆分为多个apk,这样可以有效减少apk体积。当用户下载应用程序安装包时,只会包含对应平台的so和资源。因为需要google play支持,所以国内就没有用了。
在这里插入图片描述在这里插入图片描述

找到了apk中的so文件,剩下的就是把so文件提取出来了。下面的逻辑就是从apk包中拷贝so文件到指定的目录下,并修改了文件的权限。最后剩下的只是需要加载这个so就可以了。
在这里插入图片描述

这个开源库本身不复杂,逻辑也比较简单。但是感觉网络上关于Relinker的文章比较少,这里做一些简单的分析,希望对大家有用。
————————————————
版权声明:本文为CSDN博主「viclee108」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/goodlixueyong/article/details/84710220

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值