类加载器

虚拟机设计团队把类加载阶段中的“通过一个类的全限定名来获取此类的二进制字节流”这个动作放到 Java 虚拟机外部去实现,以便让应用程序自己决定如何去获取所需要的类。实现这个动作的代码模块称为“类加载器”。

从 Java 虚拟机的角度来讲,只存在以下两种不同的类加载器:

  • 启动类加载器(Bootstrap ClassLoader),使用 C++ 实现,是虚拟机自身的一部分
  • 所有其它类的加载器,使用 Java 实现,独立于虚拟机,并且全部继承自抽象类 java.lang.ClassLoader。

从 Java 开发人员的角度看,类加载器可以划分得更细致一些:

  • 启动类加载器(Bootstrap ClassLoader):前面已经大致介绍过了,这个类加载器负责将存放在 <JRE_HOME>\lib 目录中的,或者被 -Xbootclasspath 参数所指定的路径中的,并且是虚拟机识别的(仅按照文件名识别,如 rt.jar,名字不符合的类库即使放在 lib 目录中也不会被加载)类库加载到虚拟机内存中。启动类加载器无法被 Java 程序直接引用,用户在编写自定义类加载器时,如果需要把加载请求委派给启动类加载器,直接使用 null 代替即可。
  • 扩展类加载器(Extension ClassLoader):这个类加载器是由 ExtClassLoader(sun.misc.Launcher$ExtClassLoader)实现的。它负责将 <JAVA_HOME>/lib/ext 或者被 java.ext.dir 系统变量所指定路径中的所有类库加载到内存中,开发者可以直接使用扩展类加载器。
  • 应用程序类加载器(Application ClassLoader):这个类加载器是由 AppClassLoader(sun.misc.Launcher$AppClassLoader)实现的。由于这个类加载器是 ClassLoader 中的 getSystemClassLoader() 方法的返回值,因此一般称为系统类加载器。它负责加载用户类路径(ClassPath)上所指定的类库,开发者可以直接使用这个类加载器,如果应用程序中没有自定义过自己的类加载器,一般情况下这个就是程序中默认的类加载器。

我们的应用程序都是由上述这三种类加载器互相配合从而实现类加载,如果有必要,还可以加入自己定义的类加载器。

双亲委派模型


上图是上面所介绍的这几种类加载器的层次关系,称为类加载器的双亲委派模型。该模型要求除了顶层的启动类加载器外,其它的类加载器都要有自己的父类加载器。

一言概之,双亲委派模型,其实就是一种类加载器的层次关系

1. 工作过程

如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此。

因此所有的加载请求最终都应该传送到顶层的启动类加载器中,只有当父加载器反馈自己无法完成这个加载请求(它的搜索范围中没有找到所需的类)时,子加载器才会尝试自己去加载。

在分析类加载的源码时,我们还会再一次细致的提及类加载的过程。

2. 好处

  • 使得 Java 类随着它的类加载器一起具有一种带有优先级的层次关系,从而使得基础类得到统一。 例如 java.lang.Object 存放在 rt.jar 中,如果编写另外一个 java.lang.Object 并放到 ClassPath 中,程序可以编译通过。由于双亲委派模型的存在,所以在 rt.jar 中的 Object 比在 ClassPath 中的 Object 优先级更高,这是因为 rt.jar 中的 Object 使用的是启动类加载器,而 ClassPath 中的 Object 使用的是应用程序类加载器。rt.jar 中的 Object 优先级更高,那么程序中所有的 Object 都是这个 Object。
  • 避免了多份同样字节码的加载,内存是宝贵的,没必要保存相同的两份 Class 对象,例如 System.out.println() ,实际我们需要一个 System 的 Class 对象,并且只需要一份,如果不使用委托机制,而是自己加载自己的,那么类 A 打印的时候就会加载一份 System 字节码,类 B 打印的时候又会加载一份 System 字节码。而使用委托机制就可以有效的避免这个问题。

3. 实现

双亲委派模型对于保证 Java 程序的稳定运作很重要,但它的实现却非常的简单,实现双亲委派的代码都集中在 java.lang.ClassLoader 的 loadClass() 方法中。如下所示

protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {synchronized (getClassLoadingLock(name)) {// First, check if the class has already been loadedClass<?> c = findLoadedClass(name);if (c == null) {try {if (parent != null) {c = parent.loadClass(name, false);} else {c = findBootstrapClassOrNull(name);}} catch (ClassNotFoundException e) {// ClassNotFoundException thrown if class not found// from the non-null parent class loader}if (c == null) {// If still not found, then invoke findClass in order// to find the class.c = findClass(name);}}if (resolve) {resolveClass(c);}return c;}

从 loadClass() 的源码,我们再来看一下双亲委派模型的工作过程。它可以被下面这张图来概括。

主要可以分为两步:

  • 首先从底向上的检查类是否已经加载过,就是这行代码:Class<?> c = findLoadedClass(name);
  • 如果都没有加载过的话,那么就自顶向下的尝试加载该类。

一文搞懂双亲委派模型相关推荐

  1. 摸个鱼的功夫,搞懂双亲委派机制

      大家好,我是陈哈哈,北漂儿五年~   一路走来,随着对技术的不断探索,发现不会的也愈来愈多.相信不少朋友和我一样,日积月累才是最有效的学习方式!想起高三时同桌小姐姐的座右铭:只有沉下去,才能浮上来 ...

  2. 一文搞懂鱼眼相机模型

    本文转自|计算机视觉life 鱼眼镜头 之前的文章我们介绍了针孔相机模型,相机镜头是一个凸透镜,而本文介绍的鱼眼相机镜头是由十几个不同的透镜组合而成,在成像的过程中,入射光线经过不同程度的折射,投影到 ...

  3. 一文搞懂HMM(隐马尔可夫模型)-Viterbi algorithm

    ***一文搞懂HMM(隐马尔可夫模型)*** 简单来说,熵是表示物质系统状态的一种度量,用它老表征系统的无序程度.熵越大,系统越无序,意味着系统结构和运动的不确定和无规则:反之,,熵越小,系统越有序, ...

  4. 双亲委派模型,类的加载机制,搞定大厂高频面试题

    看过这篇文章,大厂面试你「双亲委派模型」,硬气的说一句,你怕啥? 读该文章姿势 打开手头的 IDE,按照文章内容及思路进行代码跟踪与思考 手头没有 IDE,先收藏,回头看 (万一哪次面试问了呢) 需要 ...

  5. 一文搞懂如何使用ArcGIS API for Python训练深度学习模型

    一文搞懂如何使用ArcGIS API for Python训练深度学习模型 文章目录 一文搞懂如何使用ArcGIS API for Python训练深度学习模型 写在前面 一.ArcGIS API f ...

  6. 一文搞懂TCP/IP四层模型

    一文搞懂TCP/IP四层模型 上篇介绍过了OSI七层网络模型,本文将介绍四层网络模型,七层网络模型只是理论实现,但是市面上更实际的是四层模型. 七层模型和四层模型比较 将应用层,表示层,会话层这些应用 ...

  7. 一文搞懂RNN(循环神经网络)

    基础篇|一文搞懂RNN(循环神经网络) https://mp.weixin.qq.com/s/va1gmavl2ZESgnM7biORQg 神经网络基础 神经网络可以当做是能够拟合任意函数的黑盒子,只 ...

  8. python语言语句快的标记是什么_一文搞懂Python程序语句

    原标题:一文搞懂Python程序语句 程序流 Python 程序中常用的基本数据类型,包括: 内置的数值数据类型 Tuple 容器类型 String 容器类型 List 容器类型 自然的顺序是从页面或 ...

  9. Tomcat类加载器为何违背双亲委派模型

    本文来说下Tomcat类加载器为何违背双亲委派模型 文章目录 什么是类加载机制 什么是双亲委派模型 如何破坏双亲委任模型 Tomcat的类加载器是怎么设计的 本文小结 什么是类加载机制 代码编译的结果 ...

最新文章

  1. oracle parallel 并行 设置 理解
  2. css3宽度变大动画_不会仪表?太尴尬了。14种动画让你轻松掌握各种流量计工作原理...
  3. 协方差、协方差矩阵的解释意义
  4. QT的QGeoAreaMonitorSource类的使用
  5. 【新插件发布】AzureAD运维Excel版插件,增删改查快10倍c以上!
  6. 没有梦想,你跟咸鱼有什么分别?
  7. Android 雪花飘落动画效果 自定义View
  8. ASP.NET中的Cookie对象
  9. diff算法_Virtual Dom和Diff算法
  10. 190712每日一句 生命的韧性
  11. 纯js开发android,js开发app_安卓app开发引擎
  12. 【原创】EXCEL公式经验(1)---如何拆解/拆分字符串为多列和多行,但是注意不要超过EXCEL字符串最长长度限制!
  13. 海康威视rtsp转rtmp(java稳定版)
  14. 工业相机与SCARA机械臂的坐标系标定
  15. Python实现数据透视表
  16. Windows系统开机自动运行程序和自动启动服务
  17. [人物]发明了自我的人--卡帕(外二篇)
  18. 计算机派位志愿填报技巧,小升初电脑大派位:大派位操作流程及志愿填报
  19. 泛泰 A850 4.1.2 刷第三方专用Recovery合集
  20. 美妆app如何脱离流量变现难题?

热门文章

  1. 解决大部分mac用户创建项目报错问题~(通用版)
  2. 自监督论文阅读笔记 Self-supervised Learning in Remote Sensing: A Review
  3. 数据结构课程设计----车牌查询问题
  4. 服务器怎么抵御DDOS攻击?
  5. 6-2 符号函数 (5 分)(C语言版)
  6. 苹果录屏功能在哪?苹果如何进行屏幕录制?
  7. lsmod 输出内容解释
  8. 浅谈zk(3).领导者与追随者如何协作?
  9. oracle的power函数,PLSQL POWER用法及代码示例
  10. BOOT0 和 BOOT1