面试:插件化相关---so
admin
2024-03-05 03:36:37
0

关于so库的一些常识

宿主与插件中so库加载区别 :

  • 宿主应用程序 :build 生成apk ,不需要开发者自己去判断ABI,Android系统在安装APK的时候,不会安装APK里面全部的so库文件,而是会根据当前CPU类型支持的ABI,从APK里面拷贝最合适的so库,并保存在APP的内部存储路径的libs 下面。

  • 插件应用程序apk : 动态加载插件的so,需要我们判断ABI类型来加载相应的so,Android系统不会帮我们处理。

加载so的两种方式 :

  • System.load():参数必须为库文件的绝对路径(注意点:不能放在sdcard中)

  • System.loadLibrary(): 参数为库文件名,不包含库文件的扩展名

接下来,根据framework层中的源码,来了解native是如何加载,如何查找的。

PathClassLoader是如何加载代码过程

应用程序会通过PathClassLoader加载java和c++的代码

HookDemo/Android插件化之so加载.md at master · 13767004362/HookDemo · GitHub 

只要将插件中的so库放到nativeLibraryPathElements中,就可以自然而然的加载插件中c++代码了。

实战

  1. 将插件中so库解压到手机磁盘
  2. 获取到宿主中so库,与插件中so库合并收集。

1、在插件项目中先编写c++代码文件,生成对应的cpu的so库,通过System.loadLibrary()加载so库

2、接下来在宿主中编写。先根据手机cpu进行筛选,加载相应的so库,将宿主中so资源与插件so资源进行合并:

 // 获取到DexPathList对象Class baseDexClassLoaderClass = DexClassLoader.class.getSuperclass();Field pathListField = baseDexClassLoaderClass.getDeclaredField("pathList");pathListField.setAccessible(true);Object dexPathList = pathListField.get(appClassLoader);/*** 接下来,合并宿主so,系统so,插件so库*/Class DexPathListClass = dexPathList.getClass();if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1) {// 先创建一个汇总so库的文件夹,收集全部List allNativeLibDirList = new ArrayList<>();// 先添加插件的so库地址allNativeLibDirList.addAll(pluginNativeLibraryDirList);// 获取到宿主的so库地址Field nativeLibraryDirectoriesField = DexPathListClass.getDeclaredField("nativeLibraryDirectories");nativeLibraryDirectoriesField.setAccessible(true);List old_nativeLibraryDirectories = (List) nativeLibraryDirectoriesField.get(dexPathList);allNativeLibDirList.addAll(old_nativeLibraryDirectories);// 获取到system的so库地址Field systemNativeLibraryDirectoriesField = DexPathListClass.getDeclaredField("systemNativeLibraryDirectories");systemNativeLibraryDirectoriesField.setAccessible(true);List systemNativeLibraryDirectories = (List) systemNativeLibraryDirectoriesField.get(dexPathList);allNativeLibDirList.addAll(systemNativeLibraryDirectories);//通过makePathElements获取到c++存放的ElementMethod makePathElementsMethod = DexPathListClass.getDeclaredMethod("makePathElements", List.class, List.class, ClassLoader.class);makePathElementsMethod.setAccessible(true);Object[] allNativeLibraryPathElements = (Object[]) makePathElementsMethod.invoke(null, allNativeLibDirList, new ArrayList(), appClassLoader);//将合并宿主和插件的so库,重新设置进去Field nativeLibraryPathElementsField = DexPathListClass.getDeclaredField("nativeLibraryPathElements");nativeLibraryPathElementsField.setAccessible(true);nativeLibraryPathElementsField.set(dexPathList, allNativeLibraryPathElements);} else {// 获取到宿主的so库地址Field nativeLibraryDirectoriesField = DexPathListClass.getDeclaredField("nativeLibraryDirectories");nativeLibraryDirectoriesField.setAccessible(true);File[] oldNativeDirs = (File[]) nativeLibraryDirectoriesField.get(dexPathList);int oldNativeLibraryDirSize = oldNativeDirs.length;// 创建一个汇总宿主,插件的so库地址的数组File[] totalNativeLibraryDir = new File[oldNativeLibraryDirSize + pluginNativeLibraryDirList.size()];System.arraycopy(oldNativeDirs, 0, totalNativeLibraryDir, 0, oldNativeLibraryDirSize);for (int i = 0; i < totalNativeLibraryDir.length; ++i) {totalNativeLibraryDir[oldNativeLibraryDirSize + i] = pluginNativeLibraryDirList.get(i);}// 替换成合并的so库资源数组nativeLibraryDirectoriesField.set(dexPathList, totalNativeLibraryDir);}

相关内容

热门资讯

【MySQL】锁 锁 文章目录锁全局锁表级锁表锁元数据锁(MDL)意向锁AUTO-INC锁...
【内网安全】 隧道搭建穿透上线... 文章目录内网穿透-Ngrok-入门-上线1、服务端配置:2、客户端连接服务端ÿ...
GCN的几种模型复现笔记 引言 本篇笔记紧接上文,主要是上一篇看写了快2w字,再去接入代码感觉有点...
数据分页展示逻辑 import java.util.Arrays;import java.util.List;impo...
Redis为什么选择单线程?R... 目录专栏导读一、Redis版本迭代二、Redis4.0之前为什么一直采用单线程?三、R...
【已解决】ERROR: Cou... 正确指令: pip install pyyaml
关于测试,我发现了哪些新大陆 关于测试 平常也只是听说过一些关于测试的术语,但并没有使用过测试工具。偶然看到编程老师...
Lock 接口解读 前置知识点Synchronized synchronized 是 Java 中的关键字,...
Win7 专业版安装中文包、汉... 参考资料:http://www.metsky.com/archives/350.htm...
3 ROS1通讯编程提高(1) 3 ROS1通讯编程提高3.1 使用VS Code编译ROS13.1.1 VS Code的安装和配置...
大模型未来趋势 大模型是人工智能领域的重要发展趋势之一,未来有着广阔的应用前景和发展空间。以下是大模型未来的趋势和展...
python实战应用讲解-【n... 目录 如何在Python中计算残余的平方和 方法1:使用其Base公式 方法2:使用statsmod...
学习u-boot 需要了解的m... 一、常用函数 1. origin 函数 origin 函数的返回值就是变量来源。使用格式如下...
常用python爬虫库介绍与简... 通用 urllib -网络库(stdlib)。 requests -网络库。 grab – 网络库&...
药品批准文号查询|药融云-中国... 药品批文是国家食品药品监督管理局(NMPA)对药品的审评和批准的证明文件...
【2023-03-22】SRS... 【2023-03-22】SRS推流搭配FFmpeg实现目标检测 说明: 外侧测试使用SRS播放器测...
有限元三角形单元的等效节点力 文章目录前言一、重新复习一下有限元三角形单元的理论1、三角形单元的形函数(Nÿ...
初级算法-哈希表 主要记录算法和数据结构学习笔记,新的一年更上一层楼! 初级算法-哈希表...
进程间通信【Linux】 1. 进程间通信 1.1 什么是进程间通信 在 Linux 系统中,进程间通信...
【Docker】P3 Dock... Docker数据卷、宿主机与挂载数据卷的概念及作用挂载宿主机配置数据卷挂载操作示例一个容器挂载多个目...