千家信息网

在android中怎么用Java加载解析so

发表于:2025-02-13 作者:千家信息网编辑
千家信息网最后更新 2025年02月13日,本篇文章为大家展示了在android中怎么用Java加载解析so,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。理论基础so的加载是一种解析式装载,这与dex有
千家信息网最后更新 2025年02月13日在android中怎么用Java加载解析so

本篇文章为大家展示了在android中怎么用Java加载解析so,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。

理论基础

so的加载是一种解析式装载,这与dex有一定区别,dex是先加载进行优化验证生成odex,再去解析odex文件,而so更像边解析边装载,在加载过程中主要解析是load段。
下面主要是以java层的so加载进行从源码上进行解析加载流程。

java层的so加载流程分析

System.loadLibrary入口点

在java层我们知道加载so文件是通过System.loadLibrary函数其实现的,下面就以其作为入口点进行分析它的调用关系和实现。
System.loadLibrary在的函数定义系统source\libcore\luni\src\main\java\java\lang\system.java的文件中。

下面是其函数定义实现。

//参数就是要加载的so文件名称 public static void loadLibrary(String libName) {         //通过调用Runtime下面的loadLibrary函数实现         //函数有两个参数,参数1是加载的so文件名,参数2 类加载器。        Runtime.getRuntime().loadLibrary(libName, VMStack.getCallingClassLoader());    }

Runtime的loadLibray解析

通过上面的System.java的loadLibrary函数我们需要继续分析Runtime.java文件中的loadLibray函数的定义实现。
Runtime的loadLibrary函数在android系统中的位置是
source\libcore\luni\src\main\java\java\lang\Runtime.java文件。

下面是Runtime的 loadLibrary函数的定义实现源码。

/*     * Searches for and loads the given shared library using the given ClassLoader.     */    void loadLibrary(String libraryName, ClassLoader loader) {        if (loader != null) {            //通过加载器去查找要加载的so文件名            String filename = loader.findLibrary(libraryName);            //查找失败            if (filename == null) {                // It's not necessarily true that the ClassLoader used                // System.mapLibraryName, but the default setup does, and it's                // misleading to say we didn't find "libMyLibrary.so" when we                // actually searched for "liblibMyLibrary.so.so".                throw new UnsatisfiedLinkError(loader + " couldn't find \"" +                                               System.mapLibraryName(libraryName) + "\"");            }            //加载so文件名            String error = doLoad(filename, loader);            if (error != null) {                throw new UnsatisfiedLinkError(error);            }            return;        }                String filename = System.mapLibraryName(libraryName);        List candidates = new ArrayList();        String lastError = null;        //循环遍历文件路径        for (String directory : mLibPaths) {            //文件路径和文件名进行拼接            String candidate = directory + filename;            candidates.add(candidate);            if (IoUtils.canOpenReadOnly(candidate)) {                String error = doLoad(candidate, loader);                if (error == null) {                    return; // We successfully loaded the library. Job done.                }                lastError = error;            }        }        if (lastError != null) {            throw new UnsatisfiedLinkError(lastError);        }        throw new UnsatisfiedLinkError("Library " + libraryName + " not found; tried " + candidates);    }

Runtime的doLoad解析

通过上面的Runtime的loadLibrary函数,我们看到加载so的函数是走到doLoad函数,那么我们就需要继续分析Runtime下的doload函数的定义实现。
Rutime下的doload函数在系统中的
source\libcore\luni\src\main\java\java\lang\Runtime.java文件中。

下面的代码是Runtime的doload函数的定义实现。

 private String doLoad(String name, ClassLoader loader) {        // Android apps are forked from the zygote, so they can't have a custom LD_LIBRARY_PATH,        // which means that by default an app's shared library directory isn't on LD_LIBRARY_PATH.        // The PathClassLoader set up by frameworks/base knows the appropriate path, so we can load        // libraries with no dependencies just fine, but an app that has multiple libraries that        // depend on each other needed to load them in most-dependent-first order.        // We added API to Android's dynamic linker so we can update the library path used for        // the currently-running process. We pull the desired path out of the ClassLoader here        // and pass it to nativeLoad so that it can call the private dynamic linker API.        // We didn't just change frameworks/base to update the LD_LIBRARY_PATH once at the        // beginning because multiple apks can run in the same process and third party code can        // use its own BaseDexClassLoader.        // We didn't just add a dlopen_with_custom_LD_LIBRARY_PATH call because we wanted any        // dlopen(3) calls made from a .so's JNI_OnLoad to work too.        // So, find out what the native library search path is for the ClassLoader in question...        String ldLibraryPath = null;        if (loader != null && loader instanceof BaseDexClassLoader) {            ldLibraryPath = ((BaseDexClassLoader) loader).getLdLibraryPath();        }        // nativeLoad should be synchronized so there's only one LD_LIBRARY_PATH in use regardless        // of how many ClassLoaders are in the system, but dalvik doesn't support synchronized        // internal natives.        synchronized (this) {            return nativeLoad(name, loader, ldLibraryPath);        }    }

从以上的源码实现流程分析,我们可以看出Android在java层加载so的接口是System.loadLibrary(),通过层层递进关系从而实现java层的加载so。

上述内容就是在android中怎么用Java加载解析so,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注行业资讯频道。

函数 文件 分析 参数 文件名 面的 流程 源码 系统 入口 内容 就是 技能 知识 路径 装载 简明 简明扼要 两个 代码 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 北京中麦世纪网络技术服务中心 数据库课设报告 原神外网服务器 临沂量化积分管理软件开发公司 视频聊天软件开发有哪些公司 航海王热血航线应该选什么服务器 ecshop备份数据库 通信网络技术和编程一样吗 软件开发公司介绍pdf 网络安全法 环保局 在数据库中什么地方用到数据流图 荣誉证书模板软件开发 北航网络安全学院研究生招生计划 中学生网络安全调查问卷数据 软件开发身体素质 上海驰在互联网科技有限公司官网 怎么查db2数据库 化学领域有几个数据库的特点 华为算互联网还是科技 杭州庆翔网络技术有限公司 美国危害全球网络安全 如何快速备考网络技术 瑜珈下载软件开发 服务器如何增加磁盘容量 2022龙之召唤服务器排队吗 哪个服务器匹配到外国人 云服务器安全登录 非法期货软件开发人员 属于软件开发阶段的 滨海新区网络安全竞赛
0