• Android 类加载ClassLoader


    Android 中的 ClassLoader

    本质上,Android 和传统的 JVM 是一样的,也需要通过 ClassLoader 将目标类加载到内存,类加载器之间也符合双亲委派模型。但是在 Android 中, ClassLoader 的加载细节有略微的差别。

    在 Android 虚拟机里是无法直接运行 .class 文件的,Android 会将所有的 .class 文件转换成一个 .dex 文件,并且 Android 将加载 .dex 文件的实现封装在 BaseDexClassLoader 中,而我们一般只使用它的两个子类:PathClassLoader 和 DexClassLoader。

    DexClassLoader

    先来看官方对 DexClassLoader 的描述:

    A class loader that loads classes from {@code .jar} and {@code .apk} files containing a {@code classes.dex} entry. This can be used to execute code not installed as part of an application.

    DexClassLoader 可以从 SD 卡上加载包含 class.dex 的 .jar 和 .apk 文件,这也是插件化热修复的基础,在不需要安装应用的情况下,完成需要使用的 dex 的加载。

    DexClassLoader 的源码里面只有一个构造方法,代码如下:

    public class DexClassLoader extends BaseDexClassLoader {
        public DexClassLoader(String dexPath, String optimizedDirectory, String librarySearchPath, ClassLoader parent) {
            super((String)null, (File)null, (String)null, (ClassLoader)null);
            throw new RuntimeException("Stub!");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    参数说明:

    • dexPath:包含 class.dex 的 apk、jar 文件路径 ,多个路径用文件分隔符(默认是":")分隔。
    • optimizedDirectory:此参数已弃用,自 API 级别 26 起无效。
    • librarySearchPath:C/C++ native 库的路径,多个路径用文件分隔符分隔; 可能是null。
    • parent:父类加载器

    PathClassLoader

    PathClassLoader 用来加载系统 apk 和被安装到手机中的 apk 内的 dex 文件。它的 2 个构造函数如下:

    public class PathClassLoader extends BaseDexClassLoader {
        public PathClassLoader(String dexPath, ClassLoader parent) {
            super((String)null, (File)null, (String)null, (ClassLoader)null);
            throw new RuntimeException("Stub!");
        }
    
        public PathClassLoader(String dexPath, String librarySearchPath, ClassLoader parent) {
            super((String)null, (File)null, (String)null, (ClassLoader)null);
            throw new RuntimeException("Stub!");
        }
    
        @SystemApi(client = MODULE_LIBRARIES)
        public PathClassLoader(
                @NonNull String dexPath, @Nullable String librarySearchPath, @Nullable ClassLoader parent,
                @Nullable ClassLoader[] sharedLibraryLoaders) {
            super(dexPath, librarySearchPath, parent, sharedLibraryLoaders);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    参数说明:

    • dexPath:dex 文件路径,或者包含 dex 文件的 jar 包路径;
    • librarySearchPath:C/C++ native 库的路径,多个路径用文件分隔符分隔; 可能是null。
    • parent:父类加载器

    PathClassLoader 里面除了上面这些以外就没有其他的代码了,具体的实现都是在 BaseDexClassLoader 里面,其 dexPath 比较受限制,一般是已经安装应用的 apk 文件路径。

    当一个 App 被安装到手机后,apk 里面的 class.dex 中的 class 均是通过 PathClassLoader 来加载的,可以通过如下代码验证:

    public class MainActivity extends ActivityBase {
        @Override
        public void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            MLog.e(this.getClass().getName(), "onCreate");
            setContentView(R.layout.activity_main);
            ClassLoader classLoader = MainActivity.class.getClassLoader();
            MLog.e(classLoader.toString());
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    打印结果如下:

    2021-09-26 17:55:56.530 /com.scc.demo E/-SCC-com.scc.demo.actvitiy.MainActivity: onCreate
    2021-09-26 17:55:56.770 /com.scc.demo E/-SCC-:
    dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/com.scc.demo-0huSvtxqzKDw3GXvCu3P8g==/base.apk"],
    nativeLibraryDirectories=[
    /data/app/com.scc.demo-0huSvtxqzKDw3GXvCu3P8g==/lib/arm64,
    /data/app/com.scc.demo-0huSvtxqzKDw3GXvCu3P8g==/base.apk!/lib/arm64-v8a,
    /system/lib64,
    /system/product/lib64]]]
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    小结

    • ClassLoader 就是用来加载 class 文件的,不管是 jar 中还是 dex 中的 class。
    • Java 中的 ClassLoader 通过双亲委托来加载各自指定路径下的 class 文件。
    • 可以自定义 ClassLoader,一般覆盖 findClass() 方法,不建议重写 loadClass 方法。
    • Android 中常用的两种 ClassLoader 分别为:PathClassLoader 和 DexClassLoader。

    JVM
    1.Bootstrap ClassLoader /jre/lib,用于加载java虚拟机所需要的系统类,java.lang.*
    2.Ext ClassLoader /jre/lib/ext
    3.App ClassLoader

    ART
    1.BootClassLoader ->加载常用类
    2.PathClassLoader ->extends DexClassLoader,加载系统类和应用程序的类dex文件、apk等
    3.DexClassLoader ->以加载dex文件以及包含dex的apk文件或jar文件,也支持从SD卡进行加载

  • 相关阅读:
    springboot发送邮件
    如何调试 fastlane 源码
    MySql生成ER【StarUML】文件
    DECLARE_DYNAMIC提示缺少显示类型指定
    虹科培训 | 虹科携手PLCopen开展IEC 61131-3国际工程师培训
    ubuntu 搭建RKNN-Toolkit环境
    聊聊Maven的依赖传递、依赖管理、依赖作用域
    TC8:SOMEIPSRV_BASIC_01-03
    MNIST数据集手写数字识别(CNN)
    面试遇到的问题(持续更新...)
  • 原文地址:https://blog.csdn.net/weixin_44008788/article/details/128003363