首先我们要知道为什么要了解类加载机制,类加载机制是干嘛的,请看下图:
我们所编写的java文件源码通过javac命令编译成机器可以识别的字节码文件(class文件), 其中编译的过程是按照编译原理以及JVM的规范生成class文件,然后类加载的方式将class文件加载到JVM中运行,这里就是我们接下来要了解的类加载机制,也就是class文件是如何加载到JVM的运行内存中的。
类的生命周期如下:
类加载的全过程包括:装载、验证、准备、解析、初始化这五个阶段,加载的各阶段在开始时间上按上图有固定的先后顺序,但在执行时是相互交叉混合进行,通常是在一个阶段执行过程中调用或激活另一个阶段。
装载Loading
a、根据class文件所在的位置(比如jar包中、网络中、数据库中等)获取到该class文件的二进制字节流
如何获取,通过类装载器,根据类装载机制(双亲委派机制),具体请参看JVM系列之双亲委派机制的实现和作用
b、类文件的信息交给JVM---->方法区Method Area
c、类文件对应的对象交给JVM---->堆Heap
链接Linking
1、验证Verification
保证类被加载的正确性,确保Class文件的字节流中包含的信息符合JVM的要求,并且不会危害JVM自身的安全。
此阶段直接决定了JVM能否承受恶意代码的攻击。
例如:JVM系列之栈帧结构的局部变量表中两个共同存放一个64位数据的Slot不允许单独操作
2、准备Preparation
为类的静态变量(不包括类的实例变量以及方法的局部变量)分配内存空间,并将其的值初始化为默认值,如下:
//在准备阶段赋值为0,初始化阶段赋值为20
private static int value1 = 20;
//在准备阶段直接赋值为20
private static final int VALUE2 = 20;
3、解析Resolution
将常量池中的符号引用替换为直接引用
符号引用:定义在JVM规范的Class文件格式中的符号
直接引用:直接指向目标的指针、相对偏移量或者能间接定位到目标的句柄。直接引用是和JVM的内存布局相关的,如果有了直接引用,那么被引用的目标必定在内存中存在。
初始化Initialization
为静态变量赋值为初始值,执行类构造器<clinit>()方法,具体细节请参看JVM系列之类初始化执行类构造器<clinit>()方法时的细节整理