• Android Classloader


    Android 的 Classloader

    通过dex字节码来加载,合并多个class文件为一个classe.dex文件。

    Android共有三种类加载器:

    • BootClassLoader:父类构造器

    • PathClassLoader:一般是加载指定路径/data/app中的apk,也就是安装到手机中的apk。所以一般作为默认的加载器。

    • DexClassLoader:从包含classes.dex的jar或者apk中,加载类的加载器,可用于动态加载。

    PathClassLoaderDexClassLoader源码,都是继承自BaseDexClassLoader

    public DexClassLoader(String dexPath, String optimizedDirectory,
          String librarySearchPath, ClassLoader parent) {
        super(dexPath, new File(optimizedDirectory), librarySearchPath, parent);
    }
    
    
    public class PathClassLoader extends BaseDexClassLoader {
    
        public PathClassLoader(String dexPath, ClassLoader parent) {
            super(dexPath, null, null, parent);  //见下文
        }
    }
    
    public class BaseDexClassLoader extends ClassLoader {
        private final DexPathList pathList;
    
        public BaseDexClassLoader(String dexPath, File optimizedDirectory,
            String libraryPath, ClassLoader parent) {
            super(parent);  //见下文
            this.pathList = new DexPathList(this, dexPath, libraryPath, optimizedDirectory);
        }
    }
    
    

    我们可以看到PathClassLoader的两个参数都为null,表明只能接受固定的dex文件,而这个文件是只能在安装后出现的。而DexClassLoaderoptimizedDirectory,和librarySearchPath都是可以自己定义的,说明我们可以传入一个jar或者apk包,保证解压缩后是一个dex文件就可以操作了。因此,我们通常使用DexClassLoader来进行插件化和热修复。

    可以看到,BaseDexClassLoader有一个相当重要的过程就是初始化DexPathList。初始化DexPathList的过程主要是收集dexElementsnativeLibraryPathElements。一个Classloader可以包含多个dex文件,每个dex文件被封装到一个Element对象。这element对象在初始化和热修复逻辑中是相当重要的。当查找某个类时,会遍历dexElements,如果找到就返回,否则继续遍历。所以当多个dex中有相同的类,只会加载前面的dex中的类。下面是这段逻辑的具体实现

    public Class findClass(String name, List<Throwable> suppressed) {
        for (Element element : dexElements) {
            DexFile dex = element.dexFile;
            if (dex != null) {
                //找到目标类,则直接返回
                Class clazz = dex.loadClassBinaryName(name, definingContext, suppressed);
                if (clazz != null) {
                    return clazz;
                }
            }
        }
        return null;
    }
    
    

    转载自

  • 相关阅读:
    Java的参数传递是值传递还是引用传递
    10张图带你深入理解Docker容器和镜像
    Java 如何有效地避免OOM:善于利用软引用和弱引用
    事务与一致性:刚性or柔性
    Java 面试题史上最强整理
    三张图秒懂Redis集群设计原理
    iOS开发笔记系列-基础4(变量与数据类型)
    iOS开发笔记系列-基础3(多态、动态类型和动态绑定)
    iOS开发笔记系列-基础2(类)
    iOS开发笔记系列-基础1(数据类型与表达式)
  • 原文地址:https://www.cnblogs.com/huaranmeng/p/13323012.html
Copyright © 2020-2023  润新知