虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的类加载机制。
1.类加载的生命周期
1)加载
- 通过一个类的全限定名来获取定义此类的二进制字节流。(二进制字节流可以从ZIP包中读取,从网络中获取(Applet),运行时计算生成,数据库文件中读取等)
- 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。
- 在内存中生成一个代表这个类额java.lang.Class对象,作为方法区这个类的各种数据的访问入口。
2)验证
确保Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。
- 文件格式验证:字节流是否符合Class文件格式的规范,并且能被当前版本的虚拟机处理。
- 元数据验证:对字节码描述的信息进行语义分析,以保证其描述的信息符合Java语言规范的要求。
- 字节码验证:通过数据流和控制流分析,确定程序语义是合法的、符合逻辑的。
- 符号引用验证:对类自身以外的信息进行匹配性校验。
3)准备
正式为类变量分配内存并设置类变量初始值的阶段。
4)解析
虚拟机将常量池内的符号引用替换为直接引用的过程。
5)初始化
执行类构造器方法的过程。
6)使用
7)卸载
2.类加载器
1)启动类加载器(Bootstrap ClassLoader):java基本类。负责加载JAVA_HOME\lib目录中的,或通过Xbootclasspath参数指定路径中,且被虚拟机认可(.jar)的类。(不允许直接引用)
2)扩展类加载器(Extension ClassLoader):负责加载JAVA_HOME\lib\ext目录中的,或通过java.ext.dirs系统变量指定路径中的类库。(可直接使用)
3)应用程序类加载器(Application ClassLoader):负责加载用户路径(classpath)上的类库。(可直接使用)
4)线程上下文类加载器:
3.JVM加载class文件的机制
1)类的加载是指把类的 .class 文件中的数据读入到内存中,通常是创建一个字节数组读入.class 文件,然后产生与所加载类对应的 Class 对象。加载完成后,Class 对象还不完整,所以此时的类还不可用。
2)当类被加载后就进入连接阶段,这一阶段包括验证(确保class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全)、准备(为静态变量分配内存并设置默认的初始值)和解析(将符号引用替换为直接引用)三个步骤。
3)最后 JVM 对类进行初始化,包括:1. 如果类存在直接的父类并且这个类还没有被初始化,那么就先初始化父类;2. 如果类中存在初始化语句,就依次执行这些初始化语句。
4.JVM通过双亲委派模型(PDM)进行类的加载,也可以通过继承java.lang.ClassLoader实现自定义的类加载器。
双亲委派概念:当一个类加载器收到类加载请求时,会将请求先交给它的父类加载器去完成,因此所有的类加载请求都会传递到顶层的启动类加载器,只有当父加载器无法完成加载请求时,子加载器才会尝试执行加载任务。
注意:如果父加载器和子加载器加载同一个类,使用父类的。