1.4 Java代码执行过程简介
前面介绍了C/C++代码编译执行的过程,以及C++编译器如何支持面向对象的特征。本节简单介绍Java代码执行过程,JVM在执行Java代码时所做的工作,以及JVM是如何设计的。Java代码执行的过程简单可以分为以下几步:
1)Java代码被编译成字节码。
2)(可选)字节码被AOT编译器编译成可执行文件(该功能在JDK 17中被废弃)。
3)通过JVM执行字节码或者可执行文件。
JVM作为一个程序,主要包含以下功能:
1)JVM加载并解析字节码,或者JVM加载可执行文件,并解析可执行文件。为了能执行编译后的字节码,JVM中实现了一套多态处理的机制,类似于C++编译器中的虚指针、虚函数表。在介绍C++编译器时,提到了编译器把虚函数表放在数据段中,代码位于代码段。这些内容在JVM中是如何实现的?简单地说,可以认为虚函数表等信息是Java类的描述信息,而这些信息只需要保存一份即可,所以JVM设计了所谓的Klass,用于保存Java类中的描述信息。
2)JVM提供了解释执行的方案,其执行方法是把每一条字节码指令翻译成一段目标机器指令,然后执行。
3)JVM还提供了编译执行的方案,其执行方法是把一个Java函数对应的字节码或者字节码片段翻译成一段目标机器指令,在翻译的过程中还进行了编译优化,从而达到高效执行的目的。为了平衡编译时长和执行时长,JVM提供了两种编译器C1和C2。C1编译时间短但编译后的代码质量略低,C2编译时间长但编译质量高。
4)JVM提供了内存管理的功能,包括对象的快速/高效分配、垃圾回收等。
5)JVM维护和管理线程栈,最主要的原因是存在多种复杂的调用,比如Java可以调用C/C++,Java可以调用Java,C/C++本地代码也可以调用Java。
JVM整体架构图如图1-12所示。
图1-12 JVM整体架构图
下面从一个具体的实例出发,看一下Java代码是如何执行的。代码如下:
public class Example { int add(int i, int j){ return i + j; } public static void main(String [] args) { Example obj = new Example(); int result = obj.add(1,3); } }