java双亲委派机制,类加载器详解

一、类加载器概述

顾名思义,类加载器就是用来加载类到内存当中的一种工具,如果类加载不成功,你可能会遇到java.lang.ClassNotFoundException(找不到类异常)或java.lang.NoClassDefError(类没有定义错误)。在java语言中,通过JVM调用类加载器去将某一个类加载到方法区中,然后你就可以使用这个类,那么类加载器是如何去加载类的呢?是通过双亲委派机制来加载的。

二、类加载器的分类

类加载器一共可以分为4类:
1.引导类加载器【也称为根加载器】
作用:负责加载最最核心的类库,例如:JRE的核心类库中的rt.jar等,rt.jar包中包含了常见的包:java.util包、java.lang包等等,String类就是在java.lang包中。
在这里插入图片描述

2.扩展类加载器
作用:负责加载JRE目录下lib文件夹中的ext文件夹,也就是扩展库
在这里插入图片描述
3.应用程序类加载器
作用:负责加载程序员自己编写的类,或者是接口等等。比如IDEA中,默认就加载out目录下的类。
在这里插入图片描述

4.自定义类加载器
特殊情况下需要用到自定义类加载器,由于双亲委派机制只用到了上面三种类加载器,这里就不多说自定义类加载器了,很少用到。

三、双亲委托机制(类加载过程)

1.什么是双亲委托机制?
引导类加载器、扩展类加载器、应用程序类加载器三个加载器一起组合工作加载一个类,它们三种之间的工作关系就被称之为双亲委托机制。
2.什么是双亲?
1)在生活中,双亲指的就是父母
2)在类加载器中,双亲指的就是类加载器的parent属性,每一个类加载器都有一个parent属性,用来记录它的父加载器。

  • 应用程序类加载器的父加载器是扩展类加载器
  • 扩展类加载器的父加载器是引导类加载器
  • 引导类加载器没有父加载器,它已经是最上层的加载器了

3.双亲委托机制的工作过程,一共分为6个步骤
1)当系统需要加载某个类时,同时首先是应用程序类加载器先接到任务,例如:加载java.lang.String
2)应用程序类加载器接到任务之后,会先在方法区搜索这个类的Class对象,如果找到了,说明这个类已经被加载过了,那么就直接返回它的Class对象,不会重复加载。如果没有找到这个类的Class对象,会把这个任务先提交给“父加载器”,应用程序类加载器的父加载器就是扩展类加载器。
3)扩展类加载器接到任务以后,会先在方法区搜索这个类的Class对象,如果找到了,说明这个类 已经被加载过了,那么就直接返回它的Class对象,不会重复加载。如果没有找到这个类的Class对象, 会把这个任务先提交给“父加载器”,应用程序类加载器的父加载器就是引导类加载器(根加载器)。
4)引导类加载器接到任务之后,会先在方法区搜索这个类的Class对象,如果找到了,说明这个类 已经被加载过了,那么就直接返回它的Class对象,不会重复加载。如果没有找到这个类的Class对象,则会在自己负责的区域加载这个类,比如它负责的rt.jar包等,如果找到了就返回Class对象,如果没有 找到,就把任务往回传,传给扩展类加载器。
5)扩展类加载器接到父加载器回传的任务之后,就会在它负责的JRE/lib/ext目录下加载这个类,如果找到了,就返回这个Class对象,如果没找到,就把任务回传给应用程序类加载器。
6)应用程序类加载器接到父加载器回传的任务之后,就会在它负责的目录下加载整个类,例如: 项目路径下(IDEA中就是out目果找到了就返回这个类Class,如果找不到就报错ClassNotFoundException:类找不到异常
在这里插入图片描述

四、双亲委托机制的作用

1.可能有人会有疑问,为什么加载一个类需要这么复杂呢?原因只有一个:就是为了类加载安全,所以双亲委派机制就是为了安全而存在的,下面举例如果没有双亲委派机制,不安全的特殊情况。
2.例子:
某一天,程序员自己写了一个类,包名是java.lang,类名是String,完整类名就是java.lang.String,和java自带的String类完全重名,如果没有双亲委派机制,应用程序类加载器接到任务后就在自己负责的区域加载类,然后也发现了java.lang.String类,就加载到方法区中,此时你如果再想使用系统自带的String类就用不了了,因为方法区里已经有了一个java.lang.String类,你将永远无法使用系统自带的String类。
3.那么在双亲委派机制下,如果程序员自定义了一个java.lang.String类会发生什么呢?自定义的这个String类能不能使用呢?答案是:不能使用,详情看图
第一步:自定义包名是java.lang,类名是String的课
在这里插入图片描述
第二步:写代码测试能否加载到自己定义的String类
在这里插入图片描述
第三步:运行结果
在这里插入图片描述
对运行结果做一个解释:
因为有双亲委派机制,所以当你加载java.lang.String类的时候,首先应用程序类加载器会上抛给扩展类加载器,扩展类加载器上抛给引导类加载器,引导类加载器无法继续上抛,就在自己负责的区域查找,结果找到了rt.jar包中的java.lang.String类,所以就返回系统自带的String类,由于系统自带的String类中是没有main方法的,所以你执行的结果就是找不到main方法,因为此时的String类是系统自带的,而不是你自己编写的,所以双亲委派的安全作用就体现了。

五、小结

只有掌握了类加载的底层原理,以后工作了才知道找不到类异常和类没有定义错误去如何处理,对症下药,相信你已经对双亲委托机制有了很深刻的理解了,感谢阅读!

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ocean&21

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值