java 的双亲委派模型

个人笔记地址:https://app.yinxiang.com/fx/8a2ee867-dc18-49e0-a15a-2a2836061f06

Java加载的过程以及Class的 生命周期

类加载阶段:

(1)Java虚拟机将.class文件读入内存,并为之创建一个Class对象。

(2)任何类被使用时系统都会为其创建一个且仅有一个Class对象。

(3)这个Class对象描述了这个类创建出来的对象的所有信息,比如有哪些构造方法,都有哪些成员方法,都有哪些成员变量等。

 

 

双亲委派模式要求除了顶层的启动类加载器外,其余的类加载器都应当有自己的父类加载器,

请注意双亲委派模式中的父子关系并非通常所说的类继承关系,而是采用组合关系来复用父类加载器的相关代码

 

类加载器间的关系如下:

 

双亲委派模式是在Java 1.2后引入的,双亲委派的意思是如果一个类加载器需要加载类,
那么首先它会把这个类请求委派给父类加载器去完成,每一层都是如此。一直递归到顶层,如果父类加载器可以完成类加载任务,就成功返回,
当父加载器无法完成这个请求时,子类才会尝试去加载。
 
 
双亲委派模型不是一种强制性约束,也就是你不这么做也不会报错怎样的,它是一种JAVA设计者推荐使用类加载器的方式
我们可以继承java.lang.ClassLoader类,实现自己的类加载器。如果想保持双亲委派模型,就应该重写findClass(name)方法;如果想破坏双亲委派模型,可以重写loadClass(name)方法。
 
双亲委派有啥好处呢?它使得类有了层次的划分。就拿java.lang.Object来说,你加载它经过一层层委托最终是由Bootstrap ClassLoader来加载的,也就是最终都是由Bootstrap ClassLoader去找<JAVA_HOME>\lib中rt.jar里面的java.lang.Object加载到JVM中。
 
违背双亲委托的例子:
Tomcat也有自己的类加载器,比如Servlet,这些类加载器就改变了双亲委托模型的默认机制
JDBC 中mysql的驱动加载过程:
  • 第一,获取线程上下文类加载器,从而也就获得了应用程序类加载器(也可能是自定义的类加载器)
  • 第二,从META-INF/services/java.sql.Driver文件中获取具体的实现类名“com.mysql.jdbc.Driver”
  • 第三,通过线程上下文类加载器去加载这个Driver类,从而避开了双亲委派模型的弊端
很明显,mysql驱动采用的这种spi服务确确实实是破坏了双亲委派模型的,毕竟做到了父级类加载器加载了子级路径中的类。

 

 

3 双亲委派模式优势

  • 采用双亲委派模式的是好处是Java类随着它的类加载器一起具备了一种带有优先级的层次关系,通过这种层级关可以避免类的重复加载,当父亲已经加载了该类时,就没有必要子ClassLoader再加载一次。

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

  • 可能你会想,如果我们在classpath路径下自定义一个名为java.lang.SingleInterge类(该类是胡编的)呢?该类并不存在java.lang中,经过双亲委托模式,传递到启动类加载器中,由于父类加载器路径下并没有该类,所以不会加载,将反向委托给子类加载器加载,最终会通过系统类加载器加载该类。但是这样做是不允许,因为java.lang是核心API包,需要访问权限,强制加载将会报出如下异常

java.lang.SecurityException: Prohibited package name: java.lang

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值