目录
1.什么是类加载器
类加载器:用于装载字节码文件(.class文件)
JVM只会运行二进制文件,类加载器的作用就是将字节码文件加载到JVM中,从而让Java程序能够启动起来
类加载器的种类:
1.BootStrap ClassLoader(启动类加载器)
主要用来加载Java的核心类库的
load from JAVA_HOME/jre/lib
2.ExtClassLoader(扩展类加载器)
主要加载jdk下的扩展目录,加载这里边的jar包
load from JAVA_HOME/jre/lib/ext
3.AppClassLoader(应用类加载器)
加载开发者自己编写的java类
load from CLASSPATH
4.CustomizeClassLoader(自定义类加载器)
实现自定义类加载规则
2.双亲委派模型
加载某个类,先委托上一级的加载器进行加载,如果上级加载器也有上级,则会继续向上委托,如果该类委托上级没有被加载,子加载器尝试加载该类
JVM为什么采用双亲委派机制
- 通过双亲委派机制可以避免某个类被重复加载,当父类已经记载后则无需重复加载,保证唯一性
- 为了安全保证类库API不会被修改
自己写的String类,执行main函数,就会出现异常在类java.lang.String中找不到main方法
原因:所有的核心类的加载请求都会被委派给启动类加载器,所以自己定义的String不会被加载,因为启动类加载器会优先加载JRE自带的标准类,从而防止对api的修改
3.类装载的执行流程
类从加载到虚拟机中开始,直到卸载为止,它的整个生命周期包括了:加载,验证,准备,解析,初始化,使用和卸载这七个阶段。其中,验证,准备和解析这三个部分统称为连接(linking)
1.加载:
- 通过类的全名,获取类的二进制数据流
- 解析类的二进制数据流为方法区内的数据结构(Java类模型)
- 创建java.lang.Class类的实例,表示该类型。作为方法区这个类的各种数据的访问入口
比如:
有一个person类,这个类被类加载器加载后存储到运行时数据区,在运行时数据区中有两块区域进行存储。
- 方法区存储的是当前这个类的信息,person类的构造函数,方法,字段等
- 在堆中会开辟一片空间存储当前类的class对象:后期我们创建对象的时候都是基于class对象创建,构造函数,方法,字段都需要通过方法区获得,class对象可以找到方法区中的person信息,获取类的数据结构来创建对象就好了
2.验证:
验证类是否符合JVM规范,安全性检查
3.准备:
为类变量分配内存并设置类变量初始值
类变量:通过static修饰的变量叫做类变量
4.解析:
把类的符号引用转换为直接引用
比如:方法中调用了其他方法,方法名可以理解为符号引用,而直接引用就是使用指针指向方法。
5.初始化:
对类的静态变量,静态代码块执行和初始化操作
- 如果初始化一个类的时候,其父类尚未初始化,则优先初始化其父类。
- 如果同时包含多个静态变量和静态代码块,则按照自上而下的顺序依次执行。
6.使用:
JVM开始从入口方法开始执行用户的程序代码
- 调用静态成员信息(比如:静态字段,静态方法)
- 使用new关键字为其创建对象的实例
7.卸载
3.1面试题
面试官:说一下类装载的执行流程?
我: 总共分为了7个阶段
- 加载:查找和导入class文件
- 验证:保证加载类的准确性
- 准备:为类变量分配内存并设置类变量初始值
- 解析:把类中的符号引用转换成直接引用
- 初始化:对类的静态变量,静态代码块执行初始化操作
- 使用:JVM开始从入口方法开始执行用户的程序代码
- 卸载:当用户程序代码执行完毕后,JVM便开始销毁创建的Class对象