过程
加载
- 根据全限定名获取类的二进制字节流,从jar,war,ear等格式文件读取
- 字节流转为方法去的运行时数据结构
- 生成class对象,用此对象打开方法区的入口
验证
- 现在所有的class文件(这里指的是引用,还没有到实际的对象创建)都已经转为数据结构,存放在方法区
- 如果去掉验证这个步骤考虑下结果:随便写了一个java文件,内容可以是123456,这种数据对于JVM完全不认识,所以这个验证就是来看文件的内容是否是JVM认可的,就像web页面中的注册登录一样,如果没有验证,账号密码都不用输入就可以注册成功,那数据库岂不是混乱了
文件格式验证
class文件其实是一个16进制文件
- 文件的开头就是“魔数”,用来标记这是一个jvm认可的文件,魔数的值一般是0xCAFEBABE
- 而后是主,次版本号是否可以被当前jvm处理,如果环境上是jdk1.6,而自己的ide是1.8编译,那jar启动时会报错
- 然后是方法区的引用,例如:类型是class的”org/fenixsoft/clazz/TestClass” 那当前类就是TestClass,如果在当前的class文件中还有类似的引用,/org/fenixsoft/clazz/TestClassTwo,那在整个验证环节*必须要找到一个类名叫做TestClassTwo的引用加载进方法区,不然throw ClassNotFoundeClass,更细致的可以使用javap工具查看class字节码的内容,文件中会明确区分引用是class还是引用other class还是method
- 常量池的常量是否被支持
元数据验证
- 类是否是父类
- 是否继承了不允许继承的类 (final)
- 非抽象类,是否实现了父类和接口所有的方法
- 字段,方法是否和父类矛盾(覆盖父类final, 非法重载)
总结一下上面的两个步骤:
文件格式验证就是验证文件是不是JVM认识的文件,把所有的引用写入到方法区。
元数据验证就是看看方法区的引用是不是有语法错误,这里是引用只负责方法区层面(类,常量)的验证
字节码验证
这里验证的是方法体的内容
- 验证方法体内部的数据类型是否正常,如(int num = 0L这样的错误)
- 保证不会跳转到方法体以外
- 保证类型转换是否正常 (里氏替换原则)
ps:
由于方法体的庞大,1.6之后增加了StackMapTable属性来提高整体效率。
简单理解下StackMapTable:如果没有StackMapTable那JVM每次需要检查每一行代码,那把这个过程放在java编译成class的阶段,用不同的类型来计数,把这个字节码的验证前置,jvm实际验证的时候只看计数的结果,这样来提升效率
符号引用验证
- 文件格式验证阶段有一个*,说的是所有验证阶段结束后看引用是否存在。符号引用验证就是验证阶段的最后,他会做所有引用的匹配,[引用 <-> 类, 引用 <-> 方法, 引用 <-> 字段]->->->
- 检查访问性,private, protected, public, default是否可以被访问
总结四个步骤:
文件格式验证:验证class文件是否是jvm可识别的文件 元数据验证:验证方法区层面的语法 (类,常量)
字节码验证:验证方法体内部的语法 (类型转换) 符号引用验证:验证引用是否存在,访问性
四个阶段全部通过则该文件可以进行分配内存。
准备
准备阶段是正式为“类变量”分配内存并设置初始值的阶段。1
2
3
4
5public static int value = 123;
//在这个阶段value = 0
public static final int value = 123;
//在这个阶段value = 123
//javac 赋值给value的123
除了final之外,所有的类型都会给初始值1
2
3reference = null
boolean = false
int = 0
解析
解析之前先了解两个词:
- 符号引用:刚才在”文件格式验证”阶段,我们得到了类中的所有信息(类似org/abc/Test),使用的词是“引用”,它无法跟内存交互,只是用来相互定位类,方法,常亮等信息;这个“引用”就是符号引用。
- 直接引用:既然符号引用只是来互相定位,那么直接引用就是把定位的信息,真正和内存挂钩,指向目标的指针,相对偏移量,句柄。
解析的过程就是讲所有常量池中的符号引用替换为直接引用。
解析其实是另一种验证,验证阶段是建立在符号引用的表面验证;而解析是符号引用转换为直接引用过程中的二次验证
初始化
- 初始化是真正一行一行走代码,来分配内存,走static代码块
- 初始化阶段是执行类构造器的阶段 <clinit>()
- <clinit>()是自动收集类中的所有类变量和赋值动作和静态代码块
参考
文章参考 《深入理解Java虚拟机》