赞
踩
在安卓中提供了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
什么是双亲委派
加载.class文件的时候,以递归的的形式逐级向上委托给父加载器ParentClassLoader去加载,如果加载过了,就不用在加载一遍
如果父加载器也没加载过,则继续委托给父加载器去加载,一直到这条链路的顶级,顶级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; } }
loadClass方法,对于任意一个classLoader对象来说,来加载文件的时候都会调用loadClass方法.
双亲委派的作用
防止同一个.class文件重复加载
对于任意一个类确保在虚拟机中的唯一性.由加载它的类加载器和这个类的全类名一同确立其在Java虚拟机中的唯一性
保证.class文件不被篡改,通过委托方式可以保证系统类的加载逻辑不被篡改.
Android中的主要类加载器
PathClassLoader复杂的加载系统类和英勇程序的类,通常用来加载已安装apk的dex文件,实际上外部存储的dex文件也能加载
DexClassLoader可以加载dex文件以及包含dex的压缩文件(apk,dex,jar,zip)
BaseDexClassLoader实际应用层类文件的加载,而真正的加载逻辑委托给pathList来完成
BootClassLoaderAndroid平台上所有ClassLoader的最终parent,Android系统启动时会使用BootClassLoader来预加载常用类
如果想要成为架构师或想突破20~30K薪资范畴,那就不要局限在编码,业务,要会选型、扩展,提升编程思维。此外,良好的职业规划也很重要,学习的习惯很重要,但是最重要的还是要能持之以恒,任何不能坚持落实的计划都是空谈。
如果你没有方向,这里给大家分享一套由阿里高级架构师编写的《Android八大模块进阶笔记》,帮大家将杂乱、零散、碎片化的知识进行体系化的整理,让大家系统而高效地掌握Android开发的各个知识点。
相对于我们平时看的碎片化内容,这份笔记的知识点更系统化,更容易理解和记忆,是严格按照知识体系编排的。
欢迎大家一键三连支持,若需要文中资料,直接扫描文末CSDN官方认证微信卡片免费领取↓↓↓
PS:群里还设有ChatGPT机器人,可以解答大家在工作上或者是技术上的问题
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。