android中java的加载so分析

简介: so加载分析

理论基础

我们在android开发项目过程中都必然会更so加载打交道,那么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<String> candidates = new ArrayList<String>();
       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。

相关文章
|
22天前
|
移动开发 Java Android开发
构建高效Android应用:探究Kotlin与Java的性能差异
【4月更文挑战第3天】在移动开发领域,性能优化一直是开发者关注的焦点。随着Kotlin的兴起,其在Android开发中的地位逐渐上升,但关于其与Java在性能方面的对比,尚无明确共识。本文通过深入分析并结合实际测试数据,探讨了Kotlin与Java在Android平台上的性能表现,揭示了在不同场景下两者的差异及其对应用性能的潜在影响,为开发者在选择编程语言时提供参考依据。
|
30天前
|
搜索推荐 Android开发 iOS开发
安卓与iOS系统的用户界面设计对比分析
本文通过对安卓和iOS两大操作系统的用户界面设计进行对比分析,探讨它们在设计理念、交互方式、视觉风格等方面的差异及各自特点,旨在帮助读者更好地理解和评估不同系统的用户体验。
20 1
|
1月前
|
Java 编译器 Android开发
构建高效Android应用:探究Kotlin与Java的性能差异
【2月更文挑战第30天】 随着Kotlin成为开发Android应用的首选语言,开发者社区对于其性能表现持续关注。本文通过深入分析与基准测试,探讨Kotlin与Java在Android平台上的性能差异,揭示两种语言在编译效率、运行时性能和内存消耗方面的具体表现,并提供优化建议。我们的目标是为Android开发者提供科学依据,帮助他们在项目实践中做出明智的编程语言选择。
|
15天前
|
Java 调度
Java中常见锁的分类及概念分析
Java中常见锁的分类及概念分析
16 0
|
15天前
|
Java
Java中ReentrantLock中tryLock()方法加锁分析
Java中ReentrantLock中tryLock()方法加锁分析
13 0
|
29天前
|
Java 编译器 Android开发
构建高效Android应用:探究Kotlin与Java的性能差异
在开发高性能的Android应用时,选择合适的编程语言至关重要。近年来,Kotlin因其简洁性和功能性受到开发者的青睐,但其性能是否与传统的Java相比有所不足?本文通过对比分析Kotlin与Java在Android平台上的运行效率,揭示二者在编译速度、运行时性能及资源消耗方面的具体差异,并探讨在实际项目中如何做出最佳选择。
17 4
|
1月前
|
人工智能 监控 算法
java智慧城管源码 AI视频智能分析 可直接上项目
Java智慧城管源码实现AI视频智能分析,适用于直接部署项目。系统运用互联网、大数据、云计算和AI提升城市管理水平,采用“一级监督、二级指挥、四级联动”模式。功能涵盖AI智能检测(如占道广告、垃圾处理等)、执法办案、视频分析、统计分析及队伍管理等多个模块,利用深度学习优化城市管理自动化和智能化,提供决策支持。
223 4
java智慧城管源码 AI视频智能分析 可直接上项目
|
2天前
|
存储 Java Android开发
Android系统 设置第三方应用为默认Launcher实现和原理分析
Android系统 设置第三方应用为默认Launcher实现和原理分析
16 0
|
2天前
|
存储 Java Linux
Android系统获取event事件回调等几种实现和原理分析
Android系统获取event事件回调等几种实现和原理分析
21 0
|
3天前
|
Android开发
Android Mediatek NVRAM 加载 MAC 地址并禁用 MAC 地址更新
Android Mediatek NVRAM 加载 MAC 地址并禁用 MAC 地址更新
6 0