jvm类加载的五个阶段
加载,验证,准备,解析,初始化
类加载过程:
1.加载:
加载指的是将类的class文件读入到内存,通过一个类的全限定名获取此类的二进制流,将这个二进制字节流对应的静态存储结构转化为方法区运行时的数据结构,并为之创建一个java.lang.Class对象,也就是说,当程序中使用任何类时,系统都会为之建立一个java.lang.Class对象。
2.验证:
验证被加载的类是否有正确的结构,并且和其他的类协调一致,验证主要分为四种验证:文件格式验证,元数据验证,字节码验证,符号引用验证。
文件格式验证:主要验证字节流是否符合Class文件格式规范,并且能被当前的虚拟机加载处理。例如:主,次版本号是否在当前虚拟机处理的范围之内。常量池中是否有不被支持的常量类型。指向常量的中的索引值是否存在不存在的常量或不符合类型的常量。
元数据验证:对字节码描述的信息进行语义的分析,分析是否符合java的语言语法的规范。
字节码验证:最重要的验证环节,分析数据流和控制,确定语义是合法的,符合逻辑的。主要的针对元数据验证后对方法体的验证。保证类方法在运行时不会有危害出现。
符号引用验证:主要是针对符号引用转换为直接引用的时候,是会延伸到第三解析阶段,主要去确定访问类型等涉及到引用的情况,主要是要保证引用一定会被访问到,不会出现类等无法访问的问题。
3.准备:
其实就是为类的静态变量分配内存,并且设置默认值,但是final修饰的变量在编译时就已经分配完内存。
4.解析:
将类的二进制数据中的符号引用转化为直接引用
符号引用:是一一组符号来描述引用的目标,符号可以是任意的字面形式的字面量,只要不会出现冲突能够定位就行
直接引用:是指向目标的指针,偏移量或者能够直接定位的句柄。该引用是和内存中的布局相关的,并且一定加载进来的
5.初始化:
初始化为类的静态变量赋予了源文件中的正确的值,而不是默认值了。
类加载时机:
- 创建类的实例,也就是new一个对象
- 访问某个类或接口的静态变量,或者对该静态变量赋值
- 调用类的静态方法
- 使用反射机制Class.forName();Object.class;xxx.getClassloader();
- 初始化一个类的子类(会首先初始化子类的父类)
- JVM启动时标明的启动类,即文件名和类名相同的那个类