文章目录
- 什么是双亲委派?
- 为什么要有双亲委派原理?
- 破坏双亲委派的例子
————————————————————————————————
什么是双亲委派?
就是我们写的java源文件到最终运行,必须要经过编译和类加载这两个阶段。编译的过程就是把 .java 文件编译成 .class文件。
而在类加载的过程中,如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父
类加载器去完成,每一个层次的类加载器都是如此,因此所有的加载请求最终都应该传送到最顶层的启动类加载器中,只有当父
加载器反馈自己无法完成这个加载请求(它的搜索范围中没有找到所需的类)时,子加载器才会尝试自己去完成加载。
为什么要有双亲委派原理?
这样做的优点,我认为有这么几个:首先就是保证了安全性,因为这种层级关系实际代表的是一种优先级,也就是所有的类的加载,优先给启动类加载器,那么对于核心类库中的类,就没办法去破坏,比如自己写一个 java…lang.String,最终还是会交给启动类加载器,再加上每个类加载器的作用范围,那么自己写的 String 类就没办法覆盖java类库中的类。
再就是可以避免重复加载导致程序混乱的问题,因为父加载器已经加载过了,那么子类就没必要去加载了。
破坏双亲委派的例子
如何打破双亲委派机制:重写 loadclass 方法
jdbc破坏双亲委派
原生的JDBC中Driver驱动本身只是一个接口,并没有具体的实现,具体的实现是由不同数据库类型去实现的。例如,MySQL的mysql-connector-.jar中的Driver类具体实现的。 原生的JDBC中的类是放在rt.jar包的,是由启动类加载器进行类加载的,在JDBC中的Driver类中需要动态去加载不同数据库类型的Driver类,而mysql-connector-.jar中的Driver类是用户自己写的代码,那启动类加载器肯定是不能进行加载的,既然是自己编写的代码,那就需要由应用程序启动类去进行类加载。于是乎,这个时候就引入线程上下文件类加载器(Thread Context ClassLoader)。有了这个东西之后,程序就可以把原本需要由启动类加载器进行加载的类,由应用程序类加载器去进行加载了。
tomcat打破双亲委派机制
- 一个 web 容器可能需要部署两个应用程序,不同的应用程序可能会依赖同一个第三方类库的不同版本,不能要求同一个类库在同一个服务器只有一份,因此要保证每个应用程序的类库都是独立的,保证相互隔离。
- 部署在同一个 web 容器中相同的类库相同的版本可以共享。否则,如果服务器有 5 个应用程序,那么要有 5 份相同的类库加载进虚拟机,这肯定不行的。
- web 容器也有自己依赖的类库,不能和应用程序的类库混淆。基于安全考虑,应该让容器的类库和程序的类库隔离开来。
- 实现热部署。web 容器要支持 jsp 的修改,jsp 文件最终也是要编译成 class 文件才能在虚拟机中运行,但程序运行后修改 jsp 常见的事情, web 容器需要支持 jsp 修改后不用重启。