转载请注明出处:http://blog.csdn.net/linxdcn/article/details/73555233
1 概述
虚拟机规范规定,一个定义的类(class文件)被虚拟机加载到内存中,经过了3个过程:
- 加载(Loading)
- 连接(Linking)
- 验证(Verification)
- 准备(Preparation)
- 解析(Resolution)
- 初始化(Initialization)
之后这个类就能被使用了:
- 实例化(Instantiation)
下面以下面的类来说明类的加载机制:
public class ClassDemo {
public static int a = 1;
static {
System.out.println("initialized");
}
public int b = 2;
public ClassDemo() {
System.out.println("constructed");
}
}
2 加载
- 根据一个类的全限定名,找到class文件,形成class文件二进制数据流
- 初步校验,如class文件的魔数、主次版本号、访问标识等
- 解析该二进制数据流为instanceKlass对象,保存在方法区内
- 创建一个该类型的java.lang.Class实例,保存在堆中
3 连接
3.1 验证
验证是连接的第一步,大体上验证可以分为4个阶段:
- 文件格式验证(已经在上一步骤:加载中实现)
- 元数据验证
- 字节码验证
- 符号引用验证
详细的具体内容可以参考《虚拟机规范》和《深入理解Java虚拟机》。
这一步骤方法区和堆区中没有发生变化。
3.2 准备
准备阶段是为类变量(静态变量)分配内存,并将静态变量赋值默认初始值。而不是为实例变量。
默认初始值如下:
数据类型 | 默认初始值 | 数据类型 | 默认初始值 |
---|---|---|---|
int | 0 | boolean | false |
long | 0L | float | 0.0f |
short | (short)0 | double | 0.0 |
char | ‘\u0000’ | reference | null |
byte | (byte)0 |
3.3 解析
解析是虚拟机将常量池内的符号引用替换成直接引用,直接引用可以是直接指向目标的指针、相对偏移量、一个能定位到目标的句柄。
4 初始化
对类变量赋予指定的初始值,初始化阶段是执行类构造器<clinit>()
方法的过程,<clinit>()
方法由编译器按顺序收集
- 静态变量的赋值动作
- 静态语句块中的语句
5 实例化
创建类的对象实例,实例化是在类的初始化之后,是在堆上创建一个类的对象。
类的初始化会从祖先类到子类、按出现顺序,对类变量的初始化语句、静态初始化语句块依次进行初始化。而对类实例的初始化也类似,会从祖先类到子类、按出现顺序,对类成员的初始化语句、实例初始化块、构造方法依次进行初始化。
转载请注明出处:http://blog.csdn.net/linxdcn/article/details/73555233