首先看一张图,然后在进行解析:
辛苦画的此图勿盗第一个过程javac编译java的图示标注了解一下就行,现在我们就来看看第二个过程 ——> class文件如何被jvm加载的。
加载的过程分为三个:
装载(Loading)->链接(Linking)->初始化(initializing)
装载(Loading)步骤:
1. 查找到class文件,可以通过classLoader.loadClass("全类名"),从而得到二进制流;
2. 将二进制进行读取,读取出来作者、时间、版本等类信息;
3. 存储class对象;
装载过程中注意:
1. 对class文件进行验证:比如编译成class之后开头都有一个cafe babe(每个被编译成class的文件都会有这样一个格式,如下图),如果不对会有一个ClassFormatError错误;
2. classFile是否支持主要或次要的版本 否则报:UnsupportedClassVersionError;
3. 如果找不到类会报:NoClassDefFoundError;
链接(Linking)过程:
1. 验证:确保类或者接口的二进制结构是正确的,确保字节流对虚拟机是安全的(比如如果你写的一些代码能触碰到jvm底层的代码,这就不安全了);
2. 准备:主要是为类或者接口创建静态字段,并将这些字段初始化为默认值(这个默认值表示在变量初始化的时候值是0,比如 private static int a= 10,也就是这个默认值在jvm是a = 0的);
3. 解析:将类的符号引用转化为直接引用;
初始化(initializing)阶段:
1、对类的静态变量,代码块进行初始化操作,例:
public static int Flag = 1;
2、在链接(Linking)过程的准备阶段Flag = 0,在这个初始化(initializing)阶段才会赋值等于1;
结合链接过程中的那个例子分析:private static int a= 10。程序员编码的java代码中首次赋值是10,但是在jvm加载的流程中,首先其实并不是我们直接在java代码中看到的样子,而是先定义一个a变量,他的默认值是0,在初始化阶段才会再给它赋值为10。
以上就是类加载的过程。
关于下面的JVM运行时数据区另外一篇《JVM运行时数据区分析》!
网友评论