🌈hello,你好鸭,我是Ethan,西安电子科技大学大三在读,很高兴你能来阅读。
✔️目前博客主要更新Java系列、项目案例、计算机必学四件套等。
🏃人生之义,在于追求,不在成败,勤通大道。加油呀!
🔥个人主页:Ethan Yankang
🔥推荐:史上最强八股文||一分钟看完我的几百篇博客
🔥温馨提示:划到文末发现专栏彩蛋 点击这里直接传送
🔥本篇概览:详细讲解了《剑指JVM》——第19章——类加载器——类加载器层级、三大特性、双亲委派模型及优劣势。🌈⭕🔥
【计算机领域一切迷惑的源头都是基本概念的模糊,算法除外】
🌈章节引出:
前一篇章:
前面的章节讲解了类的装载过程,其中第一个阶段就是加载环节。在java语言中,实现该环节的工具就是类加载器(ClassLoader)。本章将详细介绍类加载器的相关知识。
🌈章节速览:
类加载器从文件系统或者网络中加载 class 文件到 JVM 内部,至于 class 文件是否可以运行,则由执行引擎决定,类加载器将加载的类信息存放到方法区,类加载器只能影响到类的加载,而无法改变类的链接和初始化行为。
一、 类加载分类
类的加载分为显式加载和隐式加载两种类型。显式加载指的是在代码中通过类加载的方法加载class对象,如直接使用 Class.forName(name)或 this.getClass0).getClassLoadrloadClass0)加载class对象。隐式加载则是不直接在代码中调用类加载器的方法加载 class文件,而是通过JVM自动加载到内存中)如在加载某个类的class 文件,该类的clas文件中引用了另外一个类的对象,此时额外引用的类将通过IM自动加载到内存中。在日常开发中以上两种方式一般会混合使用。
二、命名空间
对于任意一个类,都需要由加载它的类加载器和这个类本身一同确认其在JVM中的唯一性。每个类加载器都有自己的命名空间(命名空间由该类加载器及所有的父类加载器构成。在同一个命名空间中,不会出现类的完整名字(包括类的包名)相同的两个类。在不同的命名空间中,有可能会出现类的完整名字(包括类的包名)相同的两个类。
在大型应用开发中,我们常常利用这一特性,来运行同一个类的不同版本。
三、类加载机制的基本特征
通常类加载机制有三个基本特征,分别是双亲委派模型、可见性和单一性。
1.双亲委派模型
如果一个类加载器在接到加载类的请求时,它首先不会自己尝试去加载这个类,而是把这清求任务委托给父类加载器去完成,依次递归,如果父类加载器可以完成类加载任务,就成功返回。只有父类加载器无法完成此加载任务时,才自己去加载。
2.可见性
子类加载器可以访问父类加载器加载的类型,但是反过来是不允许的。
3.单一性
由于父类加载器的类型对于子类加载器是可见的,所以父类加载器中加载过的类型,就不会在子加载器中重复加载。但是注意,同一个类仍然可以被同级别的类加载器加载多次,因为互相并不可见。
JVM 支持两种类型的类加载器,分别为启动类加载器和自定义类加载器。
从概念上来讲,自定义类加载器一般指的是程序中由开发人员自定义的类加载器,在程序中我们最常见的类加载器结构如图所示,其中扩展类加载器和应用程序类由抽象类 ClassLoader派生而来:
四、双亲委派模型
1.定义与本质
类加载器用来把类文件加载到 JVM 内存中,从JDK1.2版本开始,类的加载过程采用双亲委派模型,这种机制能更好地保证 Java平台的安全。
定义
如果一个类加载器在接到加载类的请求时,它首先不会自己尝试去加载这个类,而是把这个请求任务委托给父类加载器去完成,依次递归,如果父类加载器可以完成类加载任务,就成功返回。只有父类加载器无法完成此加载任务时,才自己去加载,如图:
本质
规定了类加载的顺序。首先是引导类加载器先加载,若加载不到,由扩展类加载器加载,若还加载不到,才会由应用程序类加载器或自定义的类加载器进行加载,如图:
2.优势
1.避免类的重复加载,确保一个类的全局唯一性。
Java类随着它的类加载器一起具备了一种带有优先级的层次关系,通过这种层级关系可以避免类的重复加载,当父类加载器已经加载了该类时,子类加载器就没有必要再加载一次。这样做可以保护程序安全,防止核心API被意篡改,比如JVM不允许定义一个java.lang.String的类,会出现java.lang.SecurityException类加载器会做安全检查。
3.劣势
检查类加载的委派过程是否为单向的,这个方式虽然从结构上说比较清晰,使各个类加载器的职责非常明确但同时会带来一个问题,即顶层的类加载器无法访问底层的类加裁器所加载的类。
通常情况下,启动类加载器中的类为系统核心类,包括一些重要的系统接口。而在应用类加载器加载的类为应用类。按照这种模式,应用类访问系统类自然是没有问题,但是系统类访问应用类就会出现问题。比如在系统类中提供了一个接口,该接口需要在应用类中实现,该接口还绑定一个工厂方法,用于创建该接口的实例,而接口和工厂方法都在启动类加载器中。这时,就会出现该工厂方法无法创建由应用类加载器加载的应用实例的问题。所以Java虚拟机规范并没有明确要求类加载器的加载机制一定要使用双亲委派模型,只是建议采用这种方式而己。
比如在Tomcat中,类加载器所采用的加载机制就和传统的双亲委派模型有一定区别,当缺省的类加载器接收到一个类的加载任务时:首先会由它自行加载,当它加载失败时,才会将类的加载任务委派给它的超类加载器去执行,这同时也是Servlet规范推荐的一种
💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖
热门专栏推荐
🌈🌈计算机科学入门系列 关注走一波💕💕
🌈🌈CSAPP深入理解计算机原理 关注走一波💕💕
🌈🌈微服务项目之黑马头条 关注走一波💕💕
🌈🌈redis深度项目之黑马点评 关注走一波💕💕
🌈🌈JAVA面试八股文系列专栏 关注走一波💕💕
🌈🌈JAVA基础试题集精讲 关注走一波💕💕
🌈🌈代码随想录精讲200题 关注走一波💕💕
总栏
🌈🌈JAVA基础要夯牢 关注走一波💕💕
🌈🌈JAVA后端技术栈 关注走一波💕💕
🌈🌈JAVA面试八股文 关注走一波💕💕
🌈🌈JAVA项目(含源码深度剖析) 关注走一波💕💕
🌈🌈计算机四件套 关注走一波💕💕
🌈🌈数据结构与算法 关注走一波💕💕
🌈🌈必知必会工具集 关注走一波💕💕
🌈🌈书籍网课笔记汇总 关注走一波💕💕
📣非常感谢你阅读到这里,如果这篇文章对你有帮助,希望能留下你的点赞👍 关注❤收藏✅ 评论💬,大佬三连必回哦!thanks!!!
📚愿大家都能学有所得,功不唐捐!