编译
一个Java文件经过javac编译后生成.class文件
类加载、初始化
loading
通过一个类的全限定名获取该类的二进制流。
1.加载方式是双亲委派。双亲委派可访问下面链接
https://www.cnblogs.com/farmersun/articles/12402802.html
2.JVM规范没有规定何时必须加载,但是规定了不能LazyLoading 的五种情况
-new getstatic putstatic invokestatic指令,访问final变量除外
-java.lang.reflect对类进行反射调用时
-初始化子类的时候,父类首先初始化
-虚拟机启动时,被执行的主类必须初始化
-动态语言支持java.lang.invoke.MethodHandle解析的结果为REF_getstatic REF_putstatic REF_invokestatic的方法句柄时,该类必须初始化
3.java是混合执行(编译执行+解释执行)
字节码解释器、JIT即时编译器(如图)
检测热点代码:-XX:CompileThreshold = 10000
连接Linking
1. 验证Verification
验证的目的是为了确保Class文件的字节流中的信息安全,主要验证有:
1.文件格式验证:验证字节流是否符合Class文件的规范,如主次版本号是否在当前虚拟机范围内,常量池中的常量是否有不被支持的类型。
2.元数据验证:对字节码描述的信息进行语义分析,如这个类是否有父类,是否集成了不被继承的类等。
3.字节码验证:是整个验证过程中最复杂的一个阶段,通过验证数据流和控制流的分析,确定程序语义是否正确,主要针对方法体的验证。如:方法中的类型转换是否正确,跳转指令是否正确等。
4.符号引用验证:这个动作在后面的解析过程中发生,主要是为了确保解析动作能正确执行。
2.准备 Preparation
静态成员变量赋默认值
3. 解析Resolution
将类、方法、属性等符号引用解析为直接引用
常量池中的各种符号引用解析为指针、偏移量等内存地址的直接引用
该阶段主要完成符号引用到直接引用的转换动作。解析动作并不一定在初始化动作完成之前,也有可能在初始化之后。
初始化Initializing
在内存中生成该类的Class对象,作为该类的数据访问入口。调用类初始化代码 ,给静态成员变量赋初始值。到了初始化阶段,才真正开始执行类中定义的Java程序代码。
执行
代码执行是通过命令行来进行的