7.3双亲委派机制设计思想
目录介绍
- 01.什么是双亲委派机制
- 02.双亲委派模型工作流程
- 03.为何需要这样
- 04.代码实现案例展示
01.什么是双亲委派机制
- 主要是表示类加载器之间的层次关系
- 前提:除了顶层启动类加载器外,其余类加载器都应当有自己的父类加载器,且它们之间关系一般不会以继承(Inheritance)关系来实现,而是通过组合(Composition)关系来复用父加载器的代码。
02.双亲委派模型工作流程
- 双亲委派模型的工作流程是:
- 如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把请求委托给父加载器去完成,依次向上。
- 因此,所有的类加载请求最终都应该被传递到顶层的启动类加载器中,只有当父加载器在它的搜索范围中没有找到所需的类时,即无法完成该加载,子加载器才会尝试自己去加载该类。
- 在 java.lang.ClassLoader 中的 loadClass 方法中实现该过程。
03.为何需要这样
- 这样的好处是不同层次的类加载器具有不同优先级
- 比如所有Java对象的超级父类java.lang.Object,位于rt.jar,无论哪个类加载器加载该类,最终都是由启动类加载器进行加载,保证安全。
- 即使用户自己编写一个java.lang.Object类并放入程序中,虽能正常编译,但不会被加载运行,保证不会出现混乱。
04.代码实现案例展示
ClassLoader中loadClass方法实现了双亲委派模型
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException{ synchronized (getClassLoadingLock(name)) { //检查该类是否已经加载过 Class c = findLoadedClass(name); if (c == null) { //如果该类没有加载,则进入该分支 long t0 = System.nanoTime(); try { if (parent != null) { //当父类的加载器不为空,则通过父类的loadClass来加载该类 c = parent.loadClass(name, false); } else { //当父类的加载器为空,则调用启动类加载器来加载该类 c = findBootstrapClassOrNull(name); } } catch (ClassNotFoundException e) { //非空父类的类加载器无法找到相应的类,则抛出异常 } if (c == null) { //当父类加载器无法加载时,则调用findClass方法来加载该类 long t1 = System.nanoTime(); c = findClass(name); //用户可通过覆写该方法,来自定义类加载器 //用于统计类加载器相关的信息 sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0); sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1); sun.misc.PerfCounter.getFindClasses().increment(); } } if (resolve) { //对类进行link操作 resolveClass(c); } return c; } }
整个流程大致如下:
- a.首先,检查一下指定名称的类是否已经加载过,如果加载过了,就不需要再加载,直接返回。
- b.如果此类没有加载过,那么,再判断一下是否有父加载器;如果有父加载器,则由父加载器加载(即调用parent.loadClass(name, false);).或者是调用bootstrap类加载器来加载。
- c.如果父加载器及bootstrap类加载器都没有找到指定的类,那么调用当前类加载器的findClass方法来完成类加载。
Android | 从类加载到程序执行
- https://juejin.cn/post/6919121581180616718