当前位置:   article > 正文

Android类加载机制和双亲委派机制_android双亲委派机制

android双亲委派机制

类加载机制

在安卓中提供了3个类加载器,BootClassLoader,PathClassLoader,DexClassLoader;双亲委派机制,是委培层级上的上下层级关系,并不是说3个类加载器有父子继承关系:

类加载的委派层级

BootClassLoader -> PathClassLoader -> DexClassLoader ;

类加载器的继承结构

BootClassLoader 是父类 , PathClassLoader / DexClassLoader 是 BootClassLoader 的子类 ;

① DexClassLoader 查询 :查询自己是否加载过 A ;

如果加载过则不需要再进行加载 ;

如果没有加载过 , 则向上级 PathClassLoader 询问 是否有加载过 A ;

② PathClassLoader 查询 :查询自己是否加载过 A ;

如果加载过则不需要再进行加载 ;

如果没有加载过 , 则向上级 BootClassLoader 询问 是否有加载过 A ;

③ BootClassLoader 查询 :查询自己是否加载过 A ;

如果加载过则不需要再进行加载 ;

如果没有加载过 , 则 查询自己是否可以加载 ;

④ BootClassLoader 查询是否可以加载 :

如果自己可以加载 A , 则自己加载 ;

如果自己不可以加载 A , 则将加载任务委派给下级 PathClassLoader ;

⑤ PathClassLoader 查询是否可以加载 :

如果自己可以加载 A , 则自己加载 ;

如果自己不可以加载 A , 则将加载任务 委派给下级 DexClassLoader ;

⑥ DexClassLoader 查询是否可以加载 :

如果自己可以加载 A , 则自己加载 ;

如果自己不可以加载 A , 则 抛出 Class Not Found 异常 ;

整个过程就是 从下到上 询问 , 然后 从上到下 委派 ;

双亲委派机制

类加载器层级

由高到低 : BootClassLoader -> PathClassLoader / DexClassLoader

什么是双亲委派

  1. 加载.class文件的时候,以递归的的形式逐级向上委托给父加载器ParentClassLoader去加载,如果加载过了,就不用在加载一遍

  2. 如果父加载器也没加载过,则继续委托给父加载器去加载,一直到这条链路的顶级,顶级classLoader判断如果没加载过,则尝试加载,加载失败,则逐级向下交还调用者来加载.

双亲委派是如何实现的

任意一个classLoader对象都会有一个parent对象,我们下面的customClassLoader创建的时候虽然没有传递parent对象,但是在下面的ClassLoader类中的空参构造方法可以看出,会调用getSystemClassLoader()从而调用ClassLoader.createSystemClassLoader();,最后创建了一个PathClassLoader对象作为parent,而且在创建PathClassLoader的同时也指定了它的parent为BootClassLoader

ClassLoader customClassLoader= new ClassLoader() {

            @Override

            public Class<?> loadClass(String name) throws ClassNotFoundException {

                return super.loadClass(name);

            }

  };

public abstract class ClassLoader {

    static private class SystemClassLoader {

        public static ClassLoader loader = ClassLoader.createSystemClassLoader();

    }

    protected ClassLoader() {

        this(checkCreateClassLoader(), getSystemClassLoader());

    }

    protected ClassLoader(ClassLoader parent) {

        this(checkCreateClassLoader(), parent);

    }

    @CallerSensitive

    public static ClassLoader getSystemClassLoader() {

        return SystemClassLoader.loader;

    }

    private static ClassLoader createSystemClassLoader() {

        String classPath = System.getProperty("java.class.path", ".");

        String librarySearchPath = System.getProperty("java.library.path", "");

        //最终会调用PathClassLoader这个classLoader

        return new PathClassLoader(classPath, librarySearchPath, BootClassLoader.getInstance());

    }

    protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException{

            //1.先检查是否已经加载过--findLoaded

            Class<?> c = findLoadedClass(name);

            if (c == null) {

                try {

                    //2.如果自己没加载过,存在父类,则委托父类

                    if (parent != null) {

                        c = parent.loadClass(name, false);

                    } else {

                        c = findBootstrapClassOrNull(name);

                    }

                } catch (ClassNotFoundException e) {

                }

                if (c == null) {

                    //3.如果父类也没加载过,则尝试本级classLoader加载

                    c = findClass(name);

                }

            }

          return c;

    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93

loadClass方法,对于任意一个classLoader对象来说,来加载文件的时候都会调用loadClass方法.

  1. 先检查自己是否已经加载过class文件了–用这个findLoadedClass方法,如果已经加载了直接返回就好了
  2. 如果自己没加载过,存在父类,则委托父类去加载–用这个parent.loadClass(name, false)方法,此时就会向上传递,然后就会去父加载器中循环第1步,一直到顶级ClassLoader
  3. 如果父类也没加载过,则尝试本级classLoader加载,如果加载失败了就会向下传递,交给调用方来实现.class文件的加载

双亲委派的作用

  1. 防止同一个.class文件重复加载

  2. 对于任意一个类确保在虚拟机中的唯一性.由加载它的类加载器和这个类的全类名一同确立其在Java虚拟机中的唯一性

  3. 保证.class文件不被篡改,通过委托方式可以保证系统类的加载逻辑不被篡改.

Android中的主要类加载器

  1. PathClassLoader复杂的加载系统类和英勇程序的类,通常用来加载已安装apk的dex文件,实际上外部存储的dex文件也能加载

  2. DexClassLoader可以加载dex文件以及包含dex的压缩文件(apk,dex,jar,zip)

  3. BaseDexClassLoader实际应用层类文件的加载,而真正的加载逻辑委托给pathList来完成

  4. BootClassLoaderAndroid平台上所有ClassLoader的最终parent,Android系统启动时会使用BootClassLoader来预加载常用类

最后

如果想要成为架构师或想突破20~30K薪资范畴,那就不要局限在编码,业务,要会选型、扩展,提升编程思维。此外,良好的职业规划也很重要,学习的习惯很重要,但是最重要的还是要能持之以恒,任何不能坚持落实的计划都是空谈。

如果你没有方向,这里给大家分享一套由阿里高级架构师编写的《Android八大模块进阶笔记》,帮大家将杂乱、零散、碎片化的知识进行体系化的整理,让大家系统而高效地掌握Android开发的各个知识点。
img
相对于我们平时看的碎片化内容,这份笔记的知识点更系统化,更容易理解和记忆,是严格按照知识体系编排的。

欢迎大家一键三连支持,若需要文中资料,直接扫描文末CSDN官方认证微信卡片免费领取↓↓↓

PS:群里还设有ChatGPT机器人,可以解答大家在工作上或者是技术上的问题

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/247755
推荐阅读
相关标签
  

闽ICP备14008679号