• 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卡进行加载

  • 相关阅读:
    测试人生 | 97年双非学历的小哥哥,2线城市涨薪100%,我酸了......
    解读《互联网政务应用安全管理规定》网络和数据安全中的身份认证和审计合规建设
    Mac M1芯片启动项目时出现 no zstd-jni in java.library.path 问题排查
    华为服务体系:ITR流程体系详解
    C# this关键字的作用
    小李学知识之redis相关(redis面试题)
    第06章 移动端微量神经网络模型
    Xshell如何连接虚拟机
    什么是重载和重写,它们有什么区别?
    【原创】java+swing+mysql校园零食商城设计与实现
  • 原文地址:https://blog.csdn.net/weixin_44008788/article/details/128003363