java类加载阶段与代码执行顺序
一、类加载概述
在JVM执行我们写好的代码的过程中,具体是在代码中用到这个类的时候将“.class”文件加载进JVM内存里,类的加载到使用具体经过下面这几个过程:
加载 -> 验证 -> 准备 -> 解析 -> 初始化 -> 使用 -> 卸载
各阶段具体工作如下图(图片参考一):
二、各阶段工作详细描述(图片参考一)
三、实战代码理解
在含有几个“.class”文件的字节码文件中,JVM首先会载入含有main方法的字节码文件。代码执行时,首先将class文件加载进内存,在完成验证、准备、解析、初始化等操作后,开始执行main函数方法。其中初始化步骤完成静态代码块的执行以及类静态成员变量等的初始化,Java 虚拟机会通过加锁的方式来确保类的初始化方法仅被执行一次,这里的初始化步骤是线程安全的。
具体代码执行情况如下图:
Main.java文件:
1 public class Main{ 2 /* 3 代码执行时,首先将class文件加载进内存,在完成验证、准备、解析、初始化等操作后,开始执行 4 main函数方法。其中初始化步骤完成静态代码块的执行以及类静态成员变量等的初始化 5 */ 6 public static Static sta = new Static(); 7 public int a = 0; 8 public static void main(String[] args){ 9 System.out.println("A"); 10 new Main(); //这里加载过程只执行一次 11 new Main(); 12 new Static(); //也只执行一次加载过程 13 } 14 public Main(){ 15 System.out.println("B"); 16 } 17 //代码块是在实例化的时候运行的,实例化时代码块运行完才运行构造器 18 { 19 System.out.println("C"); 20 } 21 static{ 22 System.out.println("D"); 23 } 24 }
Static.java文件:
1 public class Static{ 2 static{ 3 System.out.println("E"); 4 } 5 public Static(){ 6 System.out.println("F"); 7 } 8 { 9 System.out.println("G"); 10 } 11 }
上述代码执行结果:
1 E 2 G 3 F 4 D 5 A 6 C 7 B 8 C 9 B 10 G 11 F
具体执行过程如下:
1.JVM载入Main.class文件,在类加载的初始化阶段,完成了类中的静态成员变量初始化以及静态代码块的执行,在此代码的静态成员变量初始化过程中,由于需要Static类的实例化,所以JVM将Static.class文件载入内存,完成Static的类加载过程,所以此时代码执行结果为上述的1、2、3、4(其中1、2、3执行顺序看下面解释)
2.完成Main的类加载阶段后,开始按顺序执行main方法,其中连续进行几次实例化。在实例化阶段,先进行代码块的执行,然后进行相应构造方法的执行。注意,在后续的类实例化阶段,由于前面已经进行过相应类的加载过程,所以后续不再进行对应的类初始化过程,仅仅进行实例化阶段。具体执行结果如5、6、7、8、9、10、11
参考:1.java团长公众号https://mp.weixin.qq.com/s/Xri-gc5B_cxpgWluLFgJRQ
2.狸猫技术窝《从0开始带你成为JVM实战高手》