模拟面试回答第十四问:双亲委派模型

简介(总)

对于双亲委派模型,我从几个方面来介绍,类加载,类加载器,双亲委派模型,好处,打破双亲委派以及JDK8到9模型产生的变化六个方面。

类加载(分1)

首先是类加载,当我们new一个对象实例时或者执行某类的main方法时都会触发类加载,类加载的作用就是为了让JVM认识这个类,知道它的各种信息,比如字段,方法,继承了哪些类,方法内引用了哪些对象,实例需要分配多大内存等等,类加载有五个阶段,加载、验证、准备、解析、初始化。不过本题我们关注的不是加载过程中,而是加载之前,这个类加载请求是由谁呈递的,那答案是类加载器。

类加载器(分2)

JVM设计了三层类加载器负责加载不同的类,每层类加载器都有自己负责的范围,分别是启动类加载器,扩展类加载器,应用类加载器。启动类加载器是最顶层的,负责加载JAVA_HOME/lib目录中的Jar包;扩展类加载器负责加载JAVA_HOME/lib/ext目录中的Jar包;应用类加载器负责加载当前项目路径下的类和引入的三方依赖。

双亲委派模型(分3)

那双亲委派模型就是指这些类加载器的加载优先级,子类加载器收到类请求后,优先委派给父类加载器,如果父类加载器无法加载,自己再加载,这就是双亲委派模型。

好处 (分4)

双亲委派模型有两点主要好处:

  1. 保证核心类库的安全,比如我自己写了一个java.lang.String.class放在项目路径下,属于应用类加载器负责的范围,当触发String的类加载时,应用类加载器接受到请求后不会自己加载,而是优先交给扩展类加载器,扩展类再交给启动类加载器,启动类加载器检索类库,找到了核心类java.lang.String.class,执行类加载。这证明了核心类不会被自己写的同名类替代,保证安全。
  2. 避免重复加载,当启动类加载器加载了String类之后,扩展类和应用类加载器就不会再加载了,加载请求结束了。

打破(分5)

有没有特殊场景需要打破双亲委派模型呢?有的,兄弟,有的,那就是Tomcat,这是一个Web服务器,Tomcat运行多个应用,不同应用可能使用不同的依赖版本,这是Tomcat的需求。而双亲委派模型会使这些应用加载同一个版本,所以Tomcat自己实现了WebAppClassLoader类,重写了loadClass()方法,重写逻辑变成先自己加载,找不到再委派给父类。Tomcat运行应用时为每个应用创建WebAppClassLoader实例,实现了应用隔离。

这样做的好处除了隔离性之外,还有热部署和安全性。重新部署应用时将之前WebAppClassLoader删掉,重新创建一个,不会被缓存干扰;不同的应用不能访问各自的类,因为加载器实例不同。

迭代变化(分6)

JDK8是个分水岭,类加载器和双亲委派模型都有变化,类加载器将扩展类加载器变成了平台类加载器,并且加载器的加载模式变了,不再是以前的匹配路径加载Jar包,而是加载模块,启动类加载器加载java.base等核心模块,平台累加载器加载java.sal,java.xml等非核心但常用的模块,应用类加载器加载项目中自己写的类和三方依赖,三方依赖可能是模块,也可能是原始Jar包。那模块到底是什么呢?其实就是加入了一些额外信息的Jar包,主要包括依赖信息。

这个依赖信息导致双亲委派模型也有变化,委派逻辑不再是严格的向上委派,而是根据模块间的依赖关系进行委派,比如java.xml模块依赖应用类加载器负责的A模块,那加载java.xml模块的类之前先要委托应用类加载器加载A模块,之后再加载java.xml的类。

这样做的好处就是更加灵活。

相关推荐
Mr_Xuhhh3 小时前
LeetCode 热题 100 刷题笔记:数组与排列的经典解法(续)
算法·leetcode·职场和发展
金斗潼关3 小时前
java反序列化入口方法介绍
java·开发语言·jvm·序列化·反序列化
小雷君3 小时前
SpringBoot 接口开发5个高频踩坑总结
java·spring boot·后端·面试
打瞌睡的朱尤3 小时前
3.25蓝桥杯训练
职场和发展·蓝桥杯
AI成长日志3 小时前
【笔面试算法学习专栏】堆与优先队列专题:数组中的第K个最大元素与前K个高频元素
学习·算法·面试
Cosolar4 小时前
AgentScope-Java ReActAgent 代码实现讲解
人工智能·后端·面试
gelald4 小时前
JVM - 垃圾回收
java·jvm·后端
_日拱一卒5 小时前
LeetCode:和为K的子数组
算法·leetcode·职场和发展
愤豆5 小时前
10-Java语言核心-JVM原理--字节码与执行引擎详解
java·jvm·python