JDBC、Tomcat为什么要破坏双亲委派模型?

问题一:双亲委派模型是什么

如果一个类加载器收到了加载某个类的请求,则该类加载器并不会去加载该类,而是把这个请求委派给父类加载器,每一个层次的类加载器都是如此,因此所有的类加载请求最终都会传送到顶端的启动类加载器;只有当父类加载器在其搜索范围内无法找到所需的类,并将该结果反馈给子类加载器,子类加载器会尝试去自己加载。

006y8mN6ly1g6ghzc5ff5j30mf0fndnr.jpg

双亲委派模型的好处

这样做的好处就是:Java类随着它的类加载器一起具备了一种带有优先级的层次关系。例如类java.lang.Object,它存放在rt.jar中,无论哪一个类加载器要加载这个类,最终都是委派给处于模型最顶端的启动类加载器进行加载,因此Object类在程序的各种类加载器环境中都是同一个类。相反,如果没有使用双亲委派模型,由各个类加载器自行去加载的话,如果用户自己编写了一个称为java.lang.object的类,并放在程序的ClassPath中,那系统中将会出现多个不同的Object类,Java类型体系中最基础的行为也就无法保证,应用程序也将会变得一片混乱。

其次是考虑到安全因素。假设通过网络传递一个名为java.lang.Integer的类,通过双亲委托模式传递到启动类加载器,而启动类加载器在核心Java API发现这个名字的类,发现该类已被加载,并不会重新加载网络传递的过来的java.lang.Integer,而直接返回已加载过的Integer.class,这样便可以防止核心API库被随意篡改。

问题二:JDBC为什么要破坏双亲委派模型

问题背景

在JDBC 4.0之后实际上我们不需要再调用Class.forName来加载驱动程序了,我们只需要把驱动的jar包放到工程的类加载路径里,那么驱动就会被自动加载。

这个自动加载采用的技术叫做SPI,数据库驱动厂商也都做了更新。可以看一下jar包里面的META-INF/services目录,里面有一个java.sql.Driver的文件,文件里面包含了驱动的全路径名。

使用上,我们只需要通过下面一句就可以创建数据库的连接:

Connection con =    DriverManager.getConnection(url , username , password ) ;   

问题解答

因为类加载器受到加载范围的限制,在某些情况下父类加载器无法加载到需要的文件,这时候就需要委托子类加载器去加载class文件。

JDBC的Driver接口定义在JDK中,其实现由各个数据库的服务商来提供,比如MySQL驱动包。DriverManager 类中要加载各个实现了Driver接口的类,然后进行管理,但是DriverManager位于 $JAVA_HOME中jre/lib/rt.jar 包,由BootStrap类加载器加载,而其Driver接口的实现类是位于服务商提供的 Jar 包,根据类加载机制,当被装载的类引用了另外一个类的时候,虚拟机就会使用装载第一个类的类装载器装载被引用的类。也就是说BootStrap类加载器还要去加载jar包中的Driver接口的实现类。我们知道,BootStrap类加载器默认只负责加载 $JAVA_HOME中jre/lib/rt.jar 里所有的class,所以需要由子类加载器去加载Driver实现,这就破坏了双亲委派模型。

查看DriverManager类的源码,看到在使用DriverManager的时候会触发其静态代码块,调用 loadInitialDrivers() 方法,并调用ServiceLoader.load(Driver.class) 加载所有在META-INF/services/java.sql.Driver 文件里边的类到JVM内存,完成驱动的自动加载。

    static {loadInitialDrivers();println("JDBC DriverManager initialized");}private static void loadInitialDrivers() {AccessController.doPrivileged(new PrivilegedAction<Void>() {public Void run() {ServiceLoader<Driver> loadedDrivers = ServiceLoader.load(Driver.class);Iterator<Driver> driversIterator = loadedDrivers.iterator();try{while(driversIterator.hasNext()) {driversIterator.next();}} catch(Throwable t) {// Do nothing}return null;}});}
    public static <S> ServiceLoader<S> load(Class<S> service) {ClassLoader cl = Thread.currentThread().getContextClassLoader();return ServiceLoader.load(service, cl);}

这个子类加载器是通过 Thread.currentThread().getContextClassLoader() 得到的线程上下文加载器。

那么这个上下文类加载器又是什么呢?

public Launcher() {...try {this.loader = Launcher.AppClassLoader.getAppClassLoader(var1);} catch (IOException var9) {throw new InternalError("Could not create application class loader", var9);}Thread.currentThread().setContextClassLoader(this.loader);...
}

可以看到,在 sun.misc.Launcher 初始化的时候,会获取AppClassLoader,然后将其设置为上下文类加载器,所以线程上下文类加载器默认情况下就是系统加载器

问题三:Tomcat为什么要破坏双亲委派模型

Tomcat类加载器:

1365990181_2529.png

Tomcat如何破坏双亲委派模型的呢?

每个Tomcat的webappClassLoader加载自己的目录下的class文件,不会传递给父类加载器。

事实上,tomcat之所以造了一堆自己的classloader,大致是出于下面三类目的:

  • 对于各个 webapp中的 classlib,需要相互隔离,不能出现一个应用中加载的类库会影响另一个应用的情况,而对于许多应用,需要有共享的lib以便不浪费资源。
  • jvm一样的安全性问题。使用单独的 classloader去装载 tomcat自身的类库,以免其他恶意或无意的破坏;
  • 热部署。相信大家一定为 tomcat修改文件不用重启就自动重新装载类库而惊叹吧。

延伸阅读

https://blog.csdn.net/u012129558/article/details/81540804

https://blog.csdn.net/liweisnake/article/details/8470285

转载于:https://www.cnblogs.com/yueshutong/p/11430885.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/362946.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JavaFX技巧8:美丽深层

如果要为JavaFX开发UI框架&#xff0c;请养成一种习惯&#xff0c;始终将自定义控件拆分为控件类和外观类。 来自Swing自己&#xff0c;这对我来说并不明显。 Swing还使用MVC概念并将实际的组件呈现委托给UI委托&#xff0c;但是扩展Swing的人们大多将其控件之一子类化&#xf…

dpdk之路-环境部署

dpdk实验环境部署 1、实验环境说明 vmware workstatioin 12 centos 7.5.1804 dpdk-stable-18.11.1 2、实验步骤 &#xff08;1&#xff09;虚拟机安装 http://vault.centos.org/7.5.1804/isos/x86_64/从链接下载CentOS-7-x86_64-DVD-1804.iso&#xff0c;安装时需要准备3张虚拟…

管理好我的业务人员

我所在的一家公司属于一家典型的以业务员为主的公司&#xff0c;没有业务员就无法生存下去的这样一家公司。但在平时的一些管理方面我经常会发现以下几点问题&#xff1a;1. 某些业务人员有时候认为天高皇帝远&#xff0c;我在外面工作&#xff0c;公司不可能派人跟踪管理的。2…

initial、inherit、unset、revert和all

前面的话 在CSS中&#xff0c;有4个关键字理论上可以应用于任何的CSS属性&#xff0c;它们是initial(初始)、inherit(继承)、unset(未设置)、revert(还原)。而all的取值只能是以上这4个关键字。本文将介绍initial、inherit、unset、revert和all initial 表示元素属性的初始默认…

基于知识图谱的医疗诊断系统论文

本作品禁止任何人/企业申请专利&#xff0c;禁止任何人使用本作品参加任何比赛或作为毕业设计&#xff0c;如使用本作品源码进行商业用途务必联系作者。 一.科学性 1.研究意义 信息科技经过 60 余年的发展&#xff0c;已经普及到社会生活的每一个角落。随着信息技术在国家治理、…

SpringBoot:SpringBoot简介

SpringBoot ...如今&#xff0c;有关SpringBoot的话题很多。 那么&#xff0c;SpringBoot是什么&#xff1f; SpringBoot是一个新的Spring产品组合项目&#xff0c;它通过大幅度减少所需的配置量来构建可立即投入生产的Spring应用程序。 Spring Boot通过基于运行时可用的类路径…

华为云(ECS)-linux服务器中-Ubuntu图形界面安装-解决root登录受限-VNCviwer/Teamviwer远程访问教程...

安装ubuntu-desktop 1.更新软件库 apt-get update2.升级软件 apt-get upgrade3.安装桌面 apt-get install ubuntu-desktop 解决root登录受限 华为云登录进去是guest用户&#xff0c;不能选择登录用户且不需要密码就即可登录。 登录进去会如下警告信息&#xff1a; 首先下载…

两列自适应布局的4种思路

前面的话 前面已经介绍过单列定宽单列自适应的两列布局&#xff0c;而两列自适应布局是指一列由内容撑开&#xff0c;另一列撑满剩余宽度的布局方式。本文将从float、table、flex和grid来介绍两列自适应布局的4种思路 float 【思路一】float 在单列定宽单列自适应的两列布局中…

机器学习中为什么使用one-hot编码

one-hot编码把分类数据转化为二进制格式&#xff0c;供机器学习使用。 转载于:https://www.cnblogs.com/xin-qing3/p/11447489.html

Java EE并发API教程

这是一个示例章节&#xff0c;摘自Francesco Marchioni编辑的WildFly上的实用Java EE 7开发 。 本章讨论了新的Java EE并发API&#xff08;JSR 236&#xff09; &#xff0c;它概述了使用一组托管资源在Java EE容器上并行执行任务的标准方法。 为了描述如何在您的应用程序中使…

经桥科技与湖南文化艺术产业集团合力打造“网乐潇湘”

签约仪式现场 签约仪式现场 签约仪式现场 经网1月7日讯(记者 陈飞 曹亮) 湖南经桥网络科技有限公司与湖南文化艺术产业集团“网乐潇湘”项目签约仪式隆重举行。经桥科技董事长姜志强、湖南文化艺术产业集团总经理陈介辉等领导出席此次签约仪式。 经桥科技与湖南文化艺术产业集…

文本溢出text-overflow和文本阴影text-shadow

前面的话 CSS3新增了一些关于文本的样式&#xff0c;其中text-overflow文本溢出和text-shadow文本阴影有些特别。因为它们有对应的overflow溢出属性和box-shadow盒子阴影属性。本文将详细介绍这两个作用在文本上的溢出和阴影属性 文本溢出 一般地&#xff0c;人们一提到文本溢出…

python第十三天,函数的嵌套定义,global,nonlocal关键字的使用,闭包及闭包的运算场景,装饰器...

今日内容 1. 函数的嵌套定义 2.global&#xff0c;nonlocal关键字 3.闭包及闭包的运用场景 4.装饰器 函数的嵌套定义 1. 概念&#xff1a;在一个函数内部定义另一个函数 2 .为什么要有函数的嵌套定义&#xff1a; 1) 函数fn2想要直接使用fn1函数的局部变量&#xff0c;可以将fn…

glup打包代码不更新

一开始以为是缓存问题&#xff0c;清完缓存依旧不行。找到打包文件找到自己改的代码是否生效了。发现修改过的代码生效了&#xff0c;but 相同方法存在两个。方法一中是修改后的内容&#xff0c;方法二是未修改的内容。原因&#xff1a;在打包前将原文件复制了一个副本&#xf…

.net反射简介

目录 [隐藏] 1 概述 2 一些在反射中经常使用的类 3 其它 4 示例 .net反射简介-概述 反射就是动态发现类型信息的能力。它帮助程序设计人员在程序运行时利用一些信息去动态地使用类型&#xff0c;这些信息在设计时是未知的&#xff0c;这种能力类型于后期绑定。反射还支持的更高…

带有Angular JS的Java EE 7 –第1部分

今天的帖子将向您展示如何使用Java EE 7和Angular JS构建非常简单的应用程序。 在去那里之前&#xff0c;让我告诉您一个简短的故事&#xff1a; 我不得不承认&#xff0c;我从来都不是Java语言的忠实拥护者&#xff0c;但是我仍然记得我第一次使用它。 我不记得确切的年份&am…

深入理解CSS定位中的堆叠z-index

前面的话 对于所有定位&#xff0c;最后都不免遇到两个元素试图放在同一位置上的情况。显然&#xff0c;其中一个必须盖住另一个。但&#xff0c;如何控制哪个元素放在上层&#xff0c;这就引入了属性z-index 定义 利用z-index&#xff0c;可以改变元素相互覆盖的顺序。这个属性…

初识服务发现及Consul框架的简单使用

初识服务发现及Consul框架的简单使用 1.什么是服务发现&#xff1f; 服务发现组件记录了&#xff08;大规模&#xff09;分布式系统中所有服务的信息&#xff0c;人们或者其它服务可以据此找到这些服务。 DNS 就是一个简单的例子。 当然&#xff0c;复杂系统的服务发现组件要提…

进程间的通信方式

5&#xff0c;进程间通信方式____ &#xff0c;____ &#xff0c;____ &#xff0c;____ &#xff0c;____ &#xff0c;_____。 管道 消息队列 共享内存 信号 信号量 套接字 管道通信&#xff1a;实质是管道文件操作&#xff0c;分为有名管道和 无名管道两种。 无名管…

JavaFX技巧4:总结

在为JavaFX开发自定义控件时&#xff0c;我强烈建议您遵循JavaFX核心控件的脚步&#xff0c;并使控件的API尽可能最终化&#xff0c;并在所有方法声明的前面放置“ final”关键字。 例 在FlexGanttFX中&#xff0c;我有很多看起来像这样的代码&#xff1a; public final Acti…