前言

Java是运行在Java的虚拟机(JVM)中的,在初步学习Java时,我们都知道,编写的Java源代码会被编译器编译成.class的字节码文件。然后ClassLoader负责将这些class文件给加载到JVM中去执行。

我们跑Java程序,跟JVM脱不了干系。

JVM中提供了三层的ClassLoader:

  • Bootstrap classLoader:主要负责加载核心的类库(java.lang.*等),构造ExtClassLoader和APPClassLoader。

  • ExtClassLoader:主要负责加载jre/lib/ext目录下的一些扩展的jar。

  • AppClassLoader:主要负责加载应用程序的主函数类

双亲委派机制

通俗点讲,双亲可以浅显理解为父类,当.class文件将要被加载到JVM中时,会先交由AppClassLoader去加载,这时目前的ClassLoader不会去加载,而是一直向上,让父类去加载。

  • 如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成。
  • 每一个层次的类加载器都是如此。因此,所有的加载请求最终都应该传送到顶层的启动类加载器中。
  • 只有当父加载器反馈自己无法完成这个加载请求时(搜索范围中没有找到所需的类),子加载器才会尝试自己去加载。


系统的ClassLoader只会加载指定目录下的class文件,如果想加载自己的class文件,那么就可以自定义一个ClassLoader。而且我们可以根据自己的需求,对class文件进行加密和解密。

需要注意的是,自定义加载器在“优先级”上,是最低的,所以简单来讲,自定义的classLoader去加载自己的类,一定是父级们都没有办法加载的情况下。

Why 双亲委派

通过双亲委派模型机制,类随着它的类加载器一起具备了一种带有优先级的层次关系

双亲委派这种机制能够避免核心类被篡改。例如:如果有人想替换系统级别的类:String.java。篡改它的实现,在这种机制下这些系统的类已经被Bootstrap classLoader加载过了(为什么?因为当一个类需要加载的时候,最先去尝试加载的就是BootstrapClassLoader),所以其他类加载器并没有机会再去加载,从一定程度上防止了危险代码的植入

再比如,如果没有使用双亲委派模型,由各个类加载器自行去加载的话,如果用户自己编写了一个称为java.lang.Object的类,在没有双亲委派模型的情况下,将会用自定义的类加载器加载,那系统中将会出现多个不同的Object类,Java类型体系中最基础的行为也就无法保证,应用程序也将会变得一片混乱。

并且,双亲委派这种机制能够防止类的重复加载

打破双亲委派模型的历史

1.第一次破坏

由于双亲委派模型是在JDK1.2之后才被引入的,而类加载器和抽象类java.lang.ClassLoader则在JDK1.0时代就已经存在,面对已经存在的用户自定义类加载器的实现代码,Java设计者引入双亲委派模型时不得不做出一些妥协。

在此之前,用户去继承java.lang.ClassLoader的唯一目的就是为了重写loadClass()方法,这是因为虚拟机在进行类加载的时候会调用加载器的私有方法loadClassInternal(),而这个方法唯一逻辑就是去调用自己的loadClass()。

用户重写了loadClass才能实现自己的类加载逻辑。

2.第二次破坏

双亲委派模型的第二次“被破坏”是由这个模型自身的缺陷所导致的,双亲委派很好地解决了各个类加载器的基础类的同一问题:越基础的类由越上层的加载器进行加载

基础类之所以称为“基础”,是因为它们总是作为被用户代码调用的API,但世事往往没有绝对的完美。

如果基础类又要调用回用户的代码,那该么办?

一个典型的例子就是JNDI服务,JNDI现在已经是Java的标准服务,它的代码由启动类加载器去加载(在JDK1.3时放进去的rt.jar),但JNDI的目的就是对资源进行集中管理和查找,它需要调用由独立厂商实现并部署在应用程序的ClassPath下的JNDI接口提供者的代码,但启动类加载器不可能“认识”这些代码。

为了解决这个问题,Java设计团队只好引入了一个不太优雅的设计:线程上下文类加载器(Thread Context ClassLoader)。这个类加载器可以通过java.lang.Thread类的setContextClassLoader()方法进行设置,如果创建线程时还未设置,他将会从父线程中继承一个,如果在应用程序的全局范围内都没有设置过的话,那这个类加载器默认就是应用程序类加载器。

有了线程上下文加载器,JNDI服务就可以使用它去加载所需要的SPI代码,也就是父类加载器请求子类加载器去完成类加载的动作,这种行为实际上就是打通了双亲委派模型层次结构来逆向使用类加载器,实际上已经违背了双亲委派模型的一般性原则,但这也是无可奈何的事情。Java中所有涉及SPI的加载动作基本上都采用这种方式,例如JNDI、JDBC、JCE、JAXB和JBI等。

3.第三次破坏

双亲委派模型的第三次“被破坏”是由于用户对程序动态性的追求导致的,与热部署相关,这里所说的“动态性”指的是当前一些非常“热门”的名词:代码热替换、模块热部署等,简答的说就是机器不用重启,只要部署上就能用。

Tomcat是如何打破双亲委派机制的呢?

Tomcat自定义加载器重写了loadclass和findclass方法

Tomcat是先去本地目录加载,为了避免本地目录覆盖掉JRE的核心类,如java.lang包等,先尝试用ExtClassLoader加载,这样即能打破双亲委派机制,有避免了覆盖掉核心类。

参考

通俗易懂的双亲委派机制
浅谈双亲委派模型
Java自定义类的加载器
https://www.jianshu.com/p/166c5360a40b

Java 双亲委派模型机制相关推荐

  1. Java双亲委派模型是什么、优势在哪、双亲委派模型的破坏

    定义 双亲委派模式的工作原理的是;如果一个类加载器收到了类加载请求,它并不会自己先去加载,而是把这个请求委托给父类的加载器去执行,如果父类加载器还存在其父类加载器,则进一步向上委托,依次递归,请求最终 ...

  2. Java双亲委派模型:为什么要双亲委派?如何打破它?破在哪里?

    文章目录 一.前言 二.类加载器 三.双亲委派机制 1.什么是双亲委派 2.为什么要双亲委派? 四.破坏双亲委派 1.直接自定义类加载器加载 2.跳过AppClassLoader和ExtClassLo ...

  3. Java 双亲委派模型

    类加载器(ClassLoader) 主要负责动态加载Java类到Java虚拟机的内存空间中.类通常是按需加载,也就是第一次使用该类时才加载 双亲委派除了顶层的启动类加载器之外,其余加载器都应当有自己的 ...

  4. 15.什么是双亲委派模型?

    什么是双亲委派机制? 双亲委派机制的意思是除了顶层的启动类加载器以外,其余的类加载器,在加载之前,都会委 派给它的父加载器进行加载.这样一层层向上传递,直到祖先们都无法胜任,它才会真正的加 载. 双亲 ...

  5. Java虚拟机:对象创建过程与类加载机制、双亲委派模型

    一.对象的创建过程: 1.对象的创建过程: 对象的创建过程一般是从 new 指令(JVM层面)开始的,整个创建过程如下: (1)首先检查 new 指令的参数是否能在常量池中定位到一个类的符号引用: ( ...

  6. 28 Java类的加载机制、什么是类的加载、类的生命周期、加载:查找并加载类的二进制数据、连接、初始化、类加载器、双亲委派模型、自定义类加载器

    28Java类的加载机制 28.1.什么是类的加载 28.2.类的生命周期 28.2.1.加载:查找并加载类的二进制数据 28.2.2.连接 28.2.3.初始化 28.3.类加载器 28.4.类的加 ...

  7. java类验证和装载顺序_Java类的加载机制和双亲委派模型

    Java类的加载机制和双亲委派模型 1类的加载机制 类从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括了:加载(Loading).验证(Verification).准备(Prepar ...

  8. JAVA虚拟机类加载机制之类加载的时机双亲委派模型

    在类加载阶段中的"通过一个类的全限定名来获取描述此类的二进制字节流"这个动作放到java虚拟机外部去实现,以便让应用程序自己决定如何去获取所需要的类.实现这个动作的代码模块被称为& ...

  9. java 打破双亲委派,为什么说java spi破坏双亲委派模型?

    虽然有SPI破坏双亲委派模型的说法,但我不太认同.简单说下. 双亲委派模型(再次吐槽下这个翻译),是一种加载类的约定.这个约定的一个用处是保证安全.比如说你写Java用了String类,你怎么保证你用 ...

最新文章

  1. 约瑟夫环 猴子选大王
  2. 一起学nRF51xx 18 -  蓝牙协议栈烧录
  3. 提升Transformer效率又有新招?基于矩阵分解的线性化Attention方案
  4. HashMap 的性能因子
  5. CentOS 7下搭建配置 SVN 服务器
  6. python中hist函数参数_用hist参数解释Python,python,解读
  7. 转移指令jmp和跳转指令call
  8. 前端学习(1353)模板语法条件判断
  9. 4星|《疯狂的独角兽》:离职员工披露上市公司负面资料,以为是小说,搜索后发现是真事。...
  10. U3D-页游-检测机制-webplayer-调试方法
  11. centos系统下搭建网站环境 php+mysql+apache
  12. 共享变量在线程间的可见性
  13. React Native ActivityIndicator(菊花组件)
  14. access注入及工具使用
  15. Brave浏览器设置默认搜索引擎为百度
  16. 数据可视化一:Excel数据可视化
  17. 学霸是怎样炼成的(大一上篇)
  18. 计算机表格基础知识训练,计算机基础知识综合练习与答案
  19. 程序猿日后规划_保存网页以供日后阅读的最佳方法
  20. PXE实现批量安装部署(win与linux系统)

热门文章

  1. 软工实践2019第四次作业-结对第一次作业
  2. 机械硬盘(HDD)种类
  3. 2019.12.07日常总结
  4. 无菌一次性注射器行业全球市场规模及发展趋势调研报告
  5. 【开源方案】USB一转四 USB HUB集线器
  6. Ubuntu16.04 nvidiaGTX940、cuda10.0.130、cudnn7.5.0安装
  7. (最新版)微信现在怎样用QQ注册~
  8. 头条后台开发面试题分析
  9. 探索LeetCode【0011】盛最多水的容器(已懂)
  10. automake 的使用(一)