一、概述
本节介绍一下so的加载原理,促使我写这个小节的原因有两点:
1.可以在给App瘦身的时候提供参考依据
2.可以给so插件化提供参考依据
下面就开始看so的加载原理吧。
二、so加载原理分析
2.1.so的编译类型
在Android中只支持三种CPU架构:x86体系、mips体系、arm体系。而当前主流的是arm体系,mips体系和x86体系基本上已经被淘汰了。所以我们在做App瘦身的时候基本上可以不用考虑x86和mips架构,光从这一点就能为apk节省不少体积。
因为arm体系的CPU架构是当前主流的,所以下面只所arm体系的架构
arm体系的CPU架构目前分为两种,一种32位的,另一种是64位的。
2.1.1.
armeabi/armeabi-v7a:这两个架构都是arm类型的,主要用于Android4.0之后的CPU是32位的。其中armeabi是比较老的一个版本,其缺少对浮点数计算的硬件支持,基本已经被淘汰了,可以不用考虑。
arm64-v8a:这个架构是arm类型,主要用于Android5.0之后,CPU是64位的。
这是一个常见的目录:
在Android上启动一个App,系统都会为每个App创建一个虚拟机。Android 64位系统加载32位的so或者App,在创建一个64位虚拟机以外还会创建一个32位的虚拟机用来加载32位的so或者App。所以根本没有必要每一个CPU架构都支持,因为Android系统是向下兼容的。只需要要保留一个armeabi-v7a的CPU架构就可以了,64位的系统会在32位的虚拟机上加载它。这样可以大大的减少apk的体积。
2.2.so的加载流程
1.假设我们在jniLibs目录下创建两个目录arm64-v8a和armeabi-v7a。加载的时候优先会加载arm64-v8a,而不会加载armeabi-v7a。所以我们只需要在armeabi-v7a的目录下放so包即可。
2.2.3.加载so的两种方式
1.System.loadLibrary(path),只能加载jniLIbs目录下的so
2.System.load(path),可以加载任意路径下的so
这两种方式最终都会调用Android底层的dlopen来打开so
2.2.4、动态加载so
动态加载so:只要so文件不是app运行的时候立马加载,我们都可以把so放到服务器上慢慢的下载。
我们可以使用System.load方法加载任意路径下的so文件,所以我们在发布app的时候不需要让so和app一块打包,只需要在用到的时候从服务器上下载下来即可。从这种角度来说,只要我们的app不是打开后立马加载so,我们就没有必要把so文件和app一块打包。一旦apk中没有so包,这可以极大的缩小apk的体积。