面试专题(五):类加载机制和双亲委派模型
一、类加载机制应用程序在使用类的时候,这个类的生命周期其实包括了如上图所示的七个阶段。**使用:**就是我们平时在编码过程中用new关键字去创建一个类的实例去使用这个类。**卸载:**虚拟机通过垃圾回收机制将这个类的信息和这个类相关的实例从虚拟机内存区域中移除。一个虚拟机加载类的全过程就包括了:加载–>验证–>准备–>解析–&
一、类加载机制
应用程序在使用类的时候,这个类的生命周期其实包括了如上图所示的七个阶段。
**使用:**就是我们平时在编码过程中用new关键字去创建一个类的实例去使用这个类。
**卸载:**虚拟机通过垃圾回收机制将这个类的信息和这个类相关的实例从虚拟机内存区域中移除。
一个虚拟机加载类的全过程就包括了:加载–>验证–>准备–>解析–>初始化
**加载:**通过这个类的全限定名找到这个类所在的位置,把它从一个文件或者一个字节流转化为虚拟机内存中的一个确确实实的对象。
**验证:**验证是为了检查每个java文件所对应的class文件所形成的字节流中包含的信息符不符合虚拟机的要求,有没有危害虚拟机自身安全的代码。
**准备:**准备阶段就是为类变量(static修饰)分配内存,并设置初始值(例如int为0)。
**解析:**解析就是将常量值的引用替换为实际值的过程
**初始化:**初始化是类加载的最后一步,在初始化阶段才开始真正执行类中所定义的java代码,注意这个初始化要和我们平时构造方法初始化(构造方法是在“使用”阶段用new关键字创建实例的时候才会调用)区分开来,这个初始化动作会把类中所有用了static修饰的变量以及静态语句块执行一遍,按照我们的意愿把类变量赋给我们所定义的变量。
在类加载过程的这5个阶段中,我们在开发java程序的时候能影响的只有“加载”阶段,负责“加载”动作的东西叫“类加载器”,可以使用系统为我们提供的类加载器,也可以使用自定义的类加载器。
自定义的类加载器常常用于部署时的热替换,还有类的加密和解密。在部署程序的时候可能会把我们的class文件进行加密,在实际运行的时候首先要把加密后的class文件通过自定义的类加载器进行解密然后交给虚拟机去执行。
二、类加载器
启动类加载器Bootstrap ClassLoader,负责加载jdk安装目录<JAVA_HOME>下的lib目录下的jdk自身所带的java类,这个类加载器是我们的应用程序无法调用的。
除了上图三个类加载器我们还可以自定义类加载器,这些加载器之间存在什么样的关系呢?或者说虚拟机是如何组织这些类加载器进行工作的?这就要用到“双亲委派模型”了
三、双亲委派模型
当一个加载器不管是应用程序类加载器还是我们自定义的类加载器在进行类加载的时候它首先不会自己去加载,它首先会把加载任务委派给自己的父类加载器,比如现在有个类需要我们的自定义类加载器来加载,其实它首先会把它交给应用程序类加载器,应用程序类加载器又会把任务交给扩展类加载器,一直往上提交,直到启动类加载器。启动类加载器如果在自己的扫描范围内能找到类,它就会去加载,如果它找不到,它就会交给它的下一级子加载器去加载,以此类推,这就是双亲委派模型。
为什么jdk里要提出双亲委派模型?
可以保证我们的类有一个合适的优先级,例如Object类,它是我们系统中所有类的根类,采用双亲委派模型以后,不管是哪个类加载器来加载Object类,哪怕这个加载器是自定义类加载器,通过双亲委派模型,最终都是由启动类加载器去加载的,这样就可以保证Object这个类在程序的各个类加载器环境中都是同一个类。在虚拟机里觉得一个类是不是唯一有两个因素,第一个就是这个类本身,第二个就是加载这个类的类加载器,如果同一个类由不同的类加载器去加载,在虚拟机看来,这两个类是不同的类。
更多推荐
所有评论(0)