说一下 JVM 的主要组成部分及其作用?

image-20240711090402890

JVM包含两个子系统和两个组件,

两个子系统为Class loader(类装载)、Execution engine(执行引擎); 两个组件为Runtime data area(运行时数据区)、Native Interface(本地接口)。 Class loader(类装载):根据给定的全限定名类名(如:java.lang.Object)来装载class文件到 Runtime data area中的method area。 Execution engine(执行引擎):执行classes中的指令。 Native Interface(本地接口):与native libraries交互,是其它编程语言交互的接口。 Runtime data area(运行时数据区域):这就是我们常说的JVM的内存。

作用 : 首先通过编译器把 Java 代码转换成字节码,类加载器(ClassLoader)再把字节码加载到内存中,将其 放在运行时数据区(Runtime data area)的方法区内,

而字节码文件只是 JVM 的一套指令集规范,并不能直接交给底层操作系统去执行,因此需要特定的命令 解析器执行引擎(Execution Engine),将字节码翻译成底层系统指令,再交由 CPU 去执行, 同事,java代码中,可以调用其他语言的本地库接口(Native Interface)来,进行一些系统调用或者c 函数调用。

JVM(Java虚拟机)是Java程序运行的基础,它提供了一个运行环境,使得Java程序能够在不同的平台上运行而不需要修改代码。JVM的架构可以分为以下几个关键部分:

1. 类装载子系统(Class Loader Subsystem)

  • 作用:负责从文件系统加载.class文件到JVM中。
  • 过程:包括加载、链接和初始化三个阶段。
    • 加载:找到并加载类的二进制数据。
    • 链接:验证、准备(为静态变量分配内存并设置默认初始值)和解析(将符号引用转换为直接引用)。
    • 初始化:执行类构造器<clinit>()方法,为静态变量设置正确的初始值。

2. 执行引擎子系统(Execution Engine Subsystem)

  • 作用:将字节码转换为机器码并执行。
  • 工作原理:通常有两种方式,解释执行(逐条将字节码翻译并执行)和即时编译(JIT,将热点代码编译为本地机器码以提高执行效率)。

3. 运行时数据区(Runtime Data Area)

  • 作用:存储JVM运行时的数据。
  • 组成部分:包括方法区(存储类信息、常量、静态变量等)、堆(存储对象实例和数组)、栈(存储局部变量和操作栈)、程序计数器(存储当前执行的字节码指令的地址)和本地方法栈(为本地方法服务)。

4. 本地接口(Native Interface)

  • 作用:允许Java代码调用本地应用程序接口(如C或C++编写的库)。
  • 实现:通过Java Native Interface(JNI)或其他机制实现。

工作流程:

  1. 编译:Java源代码被编译器编译成字节码。
  2. 加载:类装载器将字节码加载到JVM的运行时数据区中。
  3. 链接:链接过程确保加载的类是有效的,并且将符号引用转换为直接引用。
  4. 初始化:类的静态变量被初始化。
  5. 执行:执行引擎将字节码转换为机器码并执行。
  6. 调用本地库:通过本地接口,Java代码可以调用用其他语言编写的本地库。

特点:

  • 平台独立性:Java代码编译成字节码,可以在任何安装了JVM的平台上运行。
  • 垃圾回收:JVM负责管理内存,包括自动回收不再使用的对象。
  • 安全性:JVM提供了安全机制,如数组边界检查,以防止恶意代码执行。

JVM的这些组件和子系统共同工作,提供了一个稳定、高效和安全的Java程序运行环境。

image-20240711090702751

下面是Java程序运行机制详细说明

  1. Java程序运行机制步骤 2.首先利用IDE集成开发工具编写Java源代码,源文件的后缀为.java; 3.再利用编译器(javac命令)将源代码编译成字节码文件,字节码文件的后缀名为.class; 4.运行字节码的工作是由解释器(java命令)来完成的。

image-20240711090827798

从上图可以看,java文件通过编译器变成了.class文件,接下来类加载器又将这些.class文件加载到JVM 中。 其实可以一句话来解释:类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运 行时数据区的方法区内,然后在堆区创建一个 java.lang.Class对象,用来封装类在方法区内的数据结 构。