Java程序的编译和执行
Java是一种独立于平台的编程语言,它不适用于一步编译。相反,它涉及两步执行,首先通过独立于操作系统的编译器;其次,在为每个操作系统定制的虚拟机 (JVM) 中。
两个主要阶段解释如下:
Principle 1: Compilation
一、来源'。 Java' 文件通过编译器,然后将源代码编码为与机器无关的编码,称为字节码。源文件中包含的每个类的内容都存储在单独的“.class”文件中。在将源代码转换为字节码时,编译器遵循以下步骤:
第 1 步:解析:读取一组 *. Java源文件并将生成的标记序列映射到 AST(抽象语法树)-节点。
第 2 步:输入:将定义的符号输入到符号表中。
第 3 步:处理注解:如果请求,则处理在指定编译单元中找到的注解。
第 4 步:属性:对语法树进行属性化。此步骤包括名称解析、类型检查和常量折叠。
第 5 步:流:对上一步中的树执行数据流分析。这包括检查分配和可达性。
第 6 步:脱糖:重写 AST 并翻译掉一些语法糖。
第 7 步:生成:生成“.Class”文件。
https://www.youtube.com/watch?v=0f-Sx81bIWQ
Principle 2: Execution
编译器生成的类文件独立于机器或操作系统,允许它们在任何系统上运行。为了运行,将主类文件(包含方法 main 的类)传递给 JVM,然后在执行最终机器代码之前经历三个主要阶段。这些阶段是:
这些状态确实包括:
- 类加载器
- 字节码验证器
- 即时编译器
让我们讨论所有 3 个阶段。
第 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 中,是默认的类加载器。非原始类加载器是用户定义的类加载器,可以对其进行编码以自定义类加载过程。非原始类加载器(如果已定义)优先于默认类加载器来加载类。
第 2 阶段:字节码验证器
类加载器加载类的字节码后,必须由字节码验证器检查它,其工作是检查指令是否执行破坏性操作。以下是进行的一些检查:
- 变量在使用前被初始化。
- 方法调用与对象引用的类型相匹配。
- 不违反访问私有数据和方法的规则。
- 局部变量访问属于运行时堆栈。
- 运行时堆栈不会溢出。
- 如果上述任何一项检查失败,则验证程序不允许加载该类。
第 3 阶段:即时编译器
这是Java程序遇到的最后一个阶段,它的工作是将加载的字节码转换为机器码。当使用 JIT 编译器时,硬件可以执行本机代码,而不是让 JVM 重复解释相同的字节码序列并招致相对冗长的翻译过程的惩罚。除非方法的执行频率较低,否则这可能会导致执行速度的性能提升。
下图可以很好地说明该过程,如下图所示,我们由此得出结论。
Conclusion: Due to the two-step execution process described above, a java program is independent of the target operating system. However, because of the same, the execution time is way more than a similar program written in a compiled platform-dependent program.
执行:
考虑简单的打印程序写在机器本地目录的某个地方。
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
Note: GFG.class file is created after the third step which means that now our entire code in the java programming language is secure encrypted as it contains only binary. In step 4 we are running that file. Refer to the below media for ease of understanding.