Java程序的编译和执行
作为一种独立于平台的编程语言,Java并不是一步到位的编译。相反,它涉及两个步骤的执行,首先是通过一个独立于操作系统的编译器;其次是在一个虚拟机(JVM)中,该虚拟机是为每个操作系统定制的。
这两个主要阶段解释如下。
原则1:编译
首先,源”.java “文件通过编译器,然后将源代码编码为独立于机器的编码,称为字节码。源文件中包含的每个类的内容都存储在一个单独的’.class’文件中。在将源代码转换为字节码时,编译器遵循以下步骤。
第1步:解析 :读取一组*.java源文件,并将产生的标记序列映射为AST(抽象语法树)节点。
第2步:输入 :将定义的符号输入到符号表中。
第3步:处理注解: 如果要求,处理在指定编译单元中发现的注解。
第4步:属性 :对语法树进行属性处理。这个步骤包括名称解析、类型检查和常量折叠。
第5步:流 :对上一步的树进行数据流分析。这包括对赋值和可达性的检查。
第6步:解糖 :重写AST并翻译掉一些句法糖。
第7步:生成 :生成”.Class “文件。
https://www.youtube.com/watch?v=0f-Sx81bIWQ
原则2:执行
编译器生成的类文件是独立于机器或操作系统的,这使得它们可以在任何系统上运行。为了运行,主类文件(包含方法main的类)被传递给JVM,然后在最终的机器代码被执行之前经历三个主要阶段。这些阶段是:
这些状态确实包括。
- 类加载器
- 字节码验证器
- 及时编译器
让我们来讨论这三个阶段。
阶段1: 类加载器
主类通过调用JVM,绕过其’.class’文件被加载到内存中。程序中引用的所有其他类都是通过类加载器加载的。
类加载器,本身就是一个对象,它创建了一个由字符串名称引用的类体的平面命名空间。方法的定义在示例下面提供,如下。
示例
// loadClass function prototype
Class r = loadClass(String className, boolean resolveIt);
// className: name of the class to be loaded
// resolveIt: flag to decide whether any referenced class should be loaded or not.
有两种类型的类加载器
- 原始的
- 非原始的
原始类加载器被嵌入到所有的JVM中,是默认的类加载器。非primordial类加载器是一个用户定义的类加载器,可以通过编码来定制类加载过程。如果定义了非primordial类加载器,那么它比默认的类加载器更适合加载类。
第二阶段: 字节码验证器
当类的字节码被类加载器加载后,必须由字节码校验器进行检查,其工作是检查指令是否执行了破坏性的操作。以下是所进行的一些检查。
- 变量在使用前已被初始化。
- 方法调用与对象引用的类型相匹配。
- 访问私有数据和方法的规则没有被违反。
- 本地变量的访问属于运行时堆栈的范围。
- 运行时堆栈没有溢出。
- 如果上述任何检查失败,验证器将不允许加载该类。
第三阶段: 即时编译器
这是java程序遇到的最后一个阶段,它的工作是将加载的字节码转换成机器码。当使用JIT编译器时,硬件可以执行本地代码,而不是让JVM重复解释相同的字节码序列,并承担相对冗长的翻译过程的惩罚。这可以导致执行速度的性能提升,除非方法的执行频率降低。
这个过程可以通过下面的图来很好地说明,如下图所示,我们由此得出结论。
结论: 由于上述的两步执行过程,一个java程序是独立于目标操作系统的。然而,由于同样的原因,执行时间要比用依赖平台的编译程序编写的类似程序要多。
执行 。
考虑到简单的打印程序被写在机器的本地目录的某个地方。
// Java Program to Illustrate Compilation and Execution
// Stages
// Main class
class GFG {
// Main driver method
public static void main(String[] args)
{
// Print command
System.out.print("Welcome to Geeks");
}
}
输出
Welcome to Geeks
让我们了解真正的编译和执行过程。
第1步: 让我们创建一个文件,在文本文件中编写简单的打印代码,并将其保存为”.java “扩展名。
第2步: 打开终端(这里我们使用的是macOS),使用下面的命令进入桌面目录,如下所示。
cd /Users/mayanksolanki/GFG.java
第3步: 让我们尝试用以下命令编译我们的程序
javac GFG.java
第4步: 最后用以下命令运行它,如下所示。
java GFG
注意: GFG.class文件是在第3步之后创建的,这意味着现在我们的整个java编程语言的代码是安全加密的,因为它只包含二进制。在第4步,我们正在运行该文件。为了便于理解,请参考下面的媒体。