「这是我参与11月更文挑战的第2天,活动详情查看:2021最后一次更文挑战」。
本篇博文,我们来讨论下JVM的小知识。大家会了解到JVM的架构设计模块,我们会简述下什么是JVM以及工作原理。除此之外,我们还会详细的谈下加载器、运行时数据区、执行引擎,这三个部分是JVM的核心构成。
什么是JVM?
众所周知,我们需要在执行之前编译或解释任何源代码。但是 Java 使用两者的组合,即编译器和解释器。
Java 程序首先被编译成 Java 字节码(二进制形式),然后一个特殊的 Java 解释器为特定平台解释它们。
Java ByteCode 是 Java 虚拟机 (JVM) 的机器语言。 JVM 将编译后的二进制字节码转换为特定的机器语言。
Java 虚拟机充当 Java 运行时环境 (JRE) 的子部分。
JVM 是一个抽象机器,它工作在现有进程的顶部。我们可以用硬件或软件来实现它。
JVM 与 Java API 相结合,构成了 Java 平台。 JVM 的基本用途是 HotSpot。
我们可以通过三种方式定义JVM:
1. 指定 Java 虚拟机工作的规范。提供实现的人可以独立选择算法。
2. 称为 Java 运行时环境 (JRE) 的实现。
3. 一个运行时实例,当您在命令提示符下编写命令以运行 java 类时,它会创建一个 JVM 实例。
JVM的工作
JVM(Java 虚拟机)充当运行时引擎来运行 Java 应用程序。 JVM 调用存在于 Java 代码中的 main 方法。
Java 虚拟机(JVM)是 JRE(Java 运行时环境)的一部分。
Java 应用程序是 WORA(一次编写,随处运行)。 这意味着我们只需编写一次 Java 程序,即可在不同平台上运行,而无需对 Java 程序进行任何更改。
当我们编译 .java 文件时,编译器会生成与 .java 文件中存在的类同名的 .class 文件(包含字节码)。
当我们运行一个 .class 文件时,它会经历不同的步骤。下图展示下一个Java文件从编译到执行的流程:
为什么需要JVM
JVM的存在是处理Java程序执行的任务,这些任务对于开发涉及 Java 的程序是必需的。Java 虚拟机执行以下任务:
加载、验证、执行代码;
提供运行时环境、一个内存区、寄存器集、垃圾收集堆;
报告致命错误,提供类文件格式
以上任务使 Java 虚拟机成为 Java 开发不可或缺的一部分。
JVM的架构设计
JVM 体系结构中有三个主要子模块:
1. 类加载器
2. 运行时数据
3. 执行引擎
以下为JVM架构图:
详细了解下各部分的详情
Java类加载器
它是 JVM 架构的组件,用于在内存中加载类。每个 JVM 都包含一个 ClassLoader。 Java 中的三个内置类加载器是:
1. 引导类加载器。这是类加载器,它是扩展类加载器的超类。它加载 rt.jar 文件。
2. 扩展类加载器。加载目录中存在的 jar 文件的是 ClassLoader。这是子 Bootstrap classLoader 和 System classloader 的父级。
3. 系统/应用类加载器。classLoader 从类路径加载类文件。这是扩展类加载器的子类。
ClassLoader 的三个重要功能是初始化、加载、链接。
1. 初始化
此操作涉及在程序块中为所有静态变量分配其特定值。在这个阶段,所有静态变量的赋值都在代码和静态块中定义。在类中从上到下执行,在类层次结构中从父到子执行。
2.加载
此操作将辅助内存中的文件加载到主内存 (RAM) 中以供执行。 Classloader读取.class文件,生成对应的二进制数据,保存在方法区。
JVM 在方法区中存储了每个 .class 文件的一些信息。这些信息是:
加载的类及其直接父类的完全限定名称。
.class 文件是否与接口、枚举或类相关。
修饰符、变量和方法信息等。
加载 .class 文件后,JVM 在堆内存中创建一个 Class 类型的对象来表示这个文件。程序员可以使用这个 Class 对象来获取类级别的信息,如类的名称、父名称、方法和变量信息等。要获取此对象引用,我们可以使用 Object 类的 getClass() 方法。
3. 链接
此操作将主程序中的不同文件组合在一起。它执行验证、准备和(可选)解析。
验证:验证阶段检查 .class 文件的正确性。这意味着它会检查文件的形成和生成是否由有效的编译器完成。如果验证失败,我们会得到一个 java.lang.Verify 异常。
准备:JVM 为类变量分配内存,并将内存初始化为默认值。
解析:解析是用直接引用替换符号引用的过程。它使用搜索方法区来定位引用的实体。
JVM 内存区
1. 方法区——它存储每个类的结构,如方法数据、字段数据、运行时池、元数据。
2. 堆——堆是对象分配发生的运行时区域。
3. 堆栈——堆栈存储程序的部分结果和局部变量。 每当创建线程时,都会同时创建 JVM 堆栈。 当我们调用一个方法时,一个新的框架会在调用过程完成的同时创建和销毁。
4. PC 寄存器——它存储当前正在执行的 JVM 指令的地址。
5. 本地方法栈——它包括任何应用程序所需的所有本地方法。 它不是用java编写的。
Java 中的执行引擎
它是 JVM 的组件,从内存位置读取数据并执行指令。 它具有三个主要组件,即虚拟处理器、解释器和 JIT 编译器。
1. 虚拟处理器
2.解释器:读取字节码流然后执行指令。
3. Just-In-Time(JIT) 编译器:它提高了性能。 JIT 同时编译具有类似功能的部分字节码,并减少编译所需的时间。
本地方法接口
它是一个框架,有助于在用不同语言(如 c、c++ 等)编写的不同应用程序之间进行通信。本机方法接口允许在 JVM 中运行的 Java 代码由库和本机应用程序调用。
本地方法库
本机库是执行引擎必不可少的本机库(C、C++)的集合。
JDK、JVM 和 JRE 之间的区别和联系
1、JVM代表Java虚拟机,JDK代表Java开发包,JRE代表Java运行环境。
2. JDK 用于开发环境,而 JRE 用于运行时环境。
3. JVM 在 JRE 环境中运行。 JRE 包含类库、Java 虚拟机和除开发工具(如编译器和调试器)之外的其他文件。
4. JRE 是 JDK 的子集。 JDK 包含 JRE 以及编译器、调试器等开发工具。
关键知识点
JVM 代表驱动 Java 代码的 Java 虚拟机。它将 Java 字节码转换为机器语言。
在这里,Java 代码被编译为字节码。这个字节码在不同的机器上被解释
JIT 代表即时编译器。JIT是Java 虚拟机的一部分。它增加了执行时间
与其他编译器机器相比,Java 的执行速度可能较慢,
结论
本文我们简单了解了Java虚拟机的架构设计及其模块内容。下篇文章,我们一起去详细探究下类的加载器的核心工作流程。
参考文献:
1,《深入理解JVM虚拟机》