JVM类加载机制学习
虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验,解析和初始化,最终形成可以被虚拟机直接使用的java类型,就是虚拟机的类加载机制。
类加载的过程
下面就分析一下这几个过程。
1、加载
”加载“是”类加机制”的第一个过程,在加载阶段,虚拟机主要完成三件事:
(1)通过一个类的全限定名来获取其定义的二进制字节流
(2)将这个字节流所代表的的静态存储结构转化为方法区的运行时数据结构
(3)在堆中生成一个代表这个类的Class
对象,作为方法区中这些数据的访问入口。
2、连接
2.1、验证
验证的主要作用就是确保被加载的类的正确性,主要是完成以下四个阶段的验证:
(1)文件格式的验证:验证.class
文件字节流是否符合class
文件的格式的规范,并且能够被当前版本的虚拟机处理。
(2)元数据验证:主要是对字节码描述的信息进行语义分析,以保证其描述的信息符合java
语言规范的要求,比如说验证这个类是不是有父类,类中的字段方法是不是和父类冲突等等。
(3)字节码验证:这是整个验证过程最复杂的阶段,主要是确定程序语义是合法的、符合逻辑的。在元数据验证阶段对数据类型做出验证后,这个阶段主要对类的方法做出分析,保证类的方法在运行时不会出现危害虚拟机安全的事。
(4)符号引用验证:它是验证的最后一个阶段,发生在虚拟机将符号引用转化为直接引用的时候。主要是对类自身以外的信息进行校验。目的是确保解析动作能够完成。
2.2、准备
准备阶段主要为类变量分配内存并设置初始值。这些内存都在方法区分配。在这个阶段我们只需要注意两点就好了,也就是类变量和初始值两个关键词:
(1)类变量(static
)会分配内存,但是实例变量不会,实例变量主要随着对象的实例化一块分配到java
堆中,
(2)这里的初始值指的是数据类型默认值,而不是代码中被显示赋予的值。比如
public static int value = 1;
在这里准备阶段过后的value值为0,而不是1。赋值为1的动作在初始化阶段。
2.3、解析
解析阶段主要是虚拟机将常量池中的符号引用转化为直接引用的过程。什么是符号应用和直接引用呢?
符号引用:以一组符号来描述所引用的目标,可以是任何形式的字面量,只要能无歧义的定位到目标就好,就好比在班级中,老师可以用张三来代表你,也可以用你的学号来代表你,但无论任何方式这些都只是一个代号(符号),这个代号指向你(符号引用)。
直接引用:直接引用是可以指向目标的指针、相对偏移量或者是一个能直接或间接定位到目标的句柄。
解析动作主要针对类或接口、字段、类方法、接口方法、方法类型、方法句柄和调用点限定符7类符号引用进行。
3、初始化
这是类加载机制的最后一步,在这个阶段,为类的静态变量赋予正确的初始值,上述的准备阶段为静态变量赋予的是虚拟机默认的初始值,此处赋予的才是程序编写者为变量分配的真正的初始值,执行静态代码块。
类的加载机制
1、全盘负责委托机制
当一个ClassLoader
加载一个类的时候,默认委托使用加载了该类调用者的ClassLoader
来加载,除非显式的使用另一个ClassLoader
,否则该类所依赖和引用的类也由这个ClassLoader
加载。
2、双亲委派机制
指先委托父类加载器寻找目标类,在找不到的情况下在自己的路径中查找并载入目标类
双亲委派机制的优势:
(1)、沙箱安全机制:比如自己写的String.class
类不会被加载,这样可以防止核心库被随意篡改;
(2)、避免类的重复加载:当父类ClassLoader
已经加载了该类的时候,就不需要子类ClassLoader
再加载一次。