当前位置: 首页 > article >正文

JVM 的组成部分有什么

JVM(Java Virtual Machine)主要由以下几个核心组成部分构成:

1. 类加载器子系统 (Class Loader Subsystem):

  • 职责: 负责加载类文件(.class 文件)到 JVM 中。

  • 主要组件:

    • 启动类加载器 (Bootstrap Class Loader):
      • 负责加载 Java 核心类库(<JAVA_HOME>/jre/lib 目录下的 rt.jar、resources.jar 等)。
      • 是用 native code(C/C++)实现的,不是 Java 类。
      • 它是所有类加载器的根。
    • 扩展类加载器 (Extension Class Loader):
      • 负责加载 Java 扩展类库(<JAVA_HOME>/jre/lib/ext 目录下的 jar 包,或者由 java.ext.dirs 系统属性指定的目录)。
      • sun.misc.Launcher$ExtClassLoader 的实例。
    • 应用程序类加载器 (Application Class Loader/System Class Loader):
      • 负责加载应用程序的类(classpath 下的类)。
      • sun.misc.Launcher$AppClassLoader 的实例。
      • 通常是默认的类加载器。
    • 自定义类加载器 (User-Defined Class Loader):
      • 开发者可以自定义类加载器,继承 java.lang.ClassLoader 类,实现特殊的类加载逻辑(例如,从网络加载类、从数据库加载类、对类进行加密解密等)。
  • 类加载机制:

    • 双亲委派模型 (Parent Delegation Model):
      • 当一个类加载器需要加载类时,它首先会委托给它的父类加载器去加载。
      • 只有当父类加载器无法加载该类时(在其搜索范围内找不到该类),才由子类加载器尝试加载。
      • 优点:
        • 避免类的重复加载。
        • 保证 Java 核心类库的安全性(防止用户自定义的类替换核心类)。
    • 加载过程:
      1. 加载 (Loading): 查找并加载类的二进制数据(.class 文件)。
      2. 链接 (Linking):
        • 验证 (Verification): 确保加载的类文件符合 JVM 规范,没有安全问题。
        • 准备 (Preparation): 为类的静态变量分配内存,并设置默认初始值(零值)。
        • 解析 (Resolution): 将类中的符号引用解析为直接引用(可选,可以延迟到运行时)。
      3. 初始化 (Initialization): 执行类的初始化代码(静态变量赋值、静态代码块)。

2. 运行时数据区 (Runtime Data Areas):

  • 职责: JVM 在运行 Java 程序时管理的内存区域。
  • 主要区域:
    • 方法区 (Method Area):
      • 存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
      • 所有线程共享。
      • 在 HotSpot VM 中,方法区也被称为“非堆”(Non-Heap)或“永久代”(Permanent Generation,JDK 1.7 及之前)/“元空间”(Metaspace,JDK 1.8 及之后)。
      • 运行时常量池 (Runtime Constant Pool): 方法区的一部分,存放编译期生成的各种字面量和符号引用。
    • 堆 (Heap):
      • 存储对象实例和数组。
      • 所有线程共享。
      • 是垃圾回收的主要区域。
      • 可以划分为新生代(Young Generation)和老年代(Old Generation)。
        • 新生代又可以划分为 Eden 区、Survivor from 区和 Survivor to 区。
    • 虚拟机栈 (VM Stack):
      • 存储方法调用的局部变量表、操作数栈、动态链接、方法出口等信息。
      • 每个线程都有自己的虚拟机栈,栈的大小可以固定也可以动态扩展。
      • 如果线程请求的栈深度大于虚拟机允许的深度,则抛出 StackOverflowError
      • 如果虚拟机栈可以动态扩展,但无法申请到足够的内存,则抛出 OutOfMemoryError
    • 本地方法栈 (Native Method Stack):
      • 与虚拟机栈类似,但用于支持 native 方法(使用 C、C++ 等编写的方法)的执行。
      • 每个线程都有自己的本地方法栈。
    • 程序计数器 (Program Counter Register):
      • 记录当前线程正在执行的字节码指令的地址(行号)。
      • 每个线程都有自己的程序计数器。
      • 是唯一一个在 Java 虚拟机规范中没有规定任何 OutOfMemoryError 情况的区域。

3. 执行引擎 (Execution Engine):

  • 职责: 负责执行 Java 字节码指令。
  • 主要组件:
    • 解释器 (Interpreter):
      • 逐条解释执行字节码指令。
      • 启动速度快,但执行速度慢。
    • 即时编译器 (JIT Compiler):
      • 将热点代码(经常执行的代码)编译为本地机器码,提高执行效率。
      • 编译需要时间,但编译后的代码执行速度快。
      • HotSpot VM 中的 JIT 编译器:
        • Client Compiler (C1): 优化速度快,但优化程度较低。
        • Server Compiler (C2): 优化速度慢,但优化程度较高。
        • 分层编译 (Tiered Compilation): 根据程序的运行情况,选择不同的编译器进行优化(JDK 1.7 引入)。
    • 垃圾回收器 (Garbage Collector):
      • 负责自动回收不再使用的对象,释放内存。
      • 不同的 JVM 实现有不同的垃圾回收器。
      • 常见的垃圾回收器:
        • Serial GC: 单线程垃圾回收器。
        • Parallel GC: 多线程垃圾回收器。
        • CMS GC (Concurrent Mark Sweep): 并发标记清除垃圾回收器。
        • G1 GC (Garbage-First): 一种面向服务端应用的垃圾回收器。
        • ZGC: 一种低延迟垃圾回收器.
        • Shenandoah: 一种低延迟垃圾回收器.
    • 本地方法接口 (JNI, Java Native Interface):
      • 允许 Java 代码调用本地方法 (C/C++ 等编写的方法).

4. 本地库接口(Native Interface):

  • 连接不同的编程语言, 为Java使用非Java代码编写的库提供支持.

JVM 架构图示:

+-----------------------------------------------------------------------------------+
|                                   JVM                                             |
+-----------------------------------------------------------------------------------+
|  +---------------------+   +------------------------+   +---------------------+  |
|  |  类加载器子系统     |   |      运行时数据区        |   |      执行引擎       |  |
|  | (Class Loader)     |   +------------------------+   +---------------------+  |
|  +---------------------+   |  +------------------+  |   |  +---------------+  |  |
|  |  - 启动类加载器       |   |  |  方法区 (Method Area) |  |   |  |  解释器       |  |  |
|  |  - 扩展类加载器       |   |  +------------------+  |   |  | (Interpreter)  |  |  |
|  |  - 应用程序类加载器    |   |  |   - 运行时常量池      |  |   |  +---------------+  |  |
|  |  - 自定义类加载器     |   |  +------------------+  |   |  +---------------+  |  |
|  +---------------------+   |  +------------------+  |   |  | 即时编译器    |  |  |
|                        |   |  |  堆 (Heap)        |  |   |  | (JIT Compiler)|  |  |
|                        |   |  +------------------+  |   |  |  - C1 (Client) |  |  |
|                        |   |  |   - 新生代       |  |   |  |  - C2 (Server) |  |  |
|                        |   |  |     - Eden       |  |   |  |  - 分层编译     |  |  |
|                        |   |  |     - Survivor   |  |   |  +---------------+  |  |
|                        |   |  |   - 老年代       |  |   |  +---------------+  |  |
|                        |   |  +------------------+  |   |  | 垃圾回收器   |  |  |
|                        |   |  +------------------+  |   |  | (GC)          |  |  |
|                        |   |  |  虚拟机栈 (VM Stack)  |  |   |  +---------------+  |  |
|                        |   |  +------------------+  |   |                        |  |
|                        |   |  +------------------+  |   |  +---------------+  |  |
|                        |   |  | 本地方法栈 (Native) |  |   |  |本地方法接口 |  |  |
|                        |   |  +------------------+  |   |  |   (JNI)       |  |  |
|                        |   |  +------------------+  |   |  +---------------+  |  |
|                        |   |  | 程序计数器 (PC)    |  |   |                        |  |
|                        |   |  +------------------+  |   |                        |  |
|                        |   +------------------------+   |                        |  |
|                        |                              |                        |  |
+-----------------------------------------------------------------------------------+

总结:

JVM 主要由类加载器子系统、运行时数据区、执行引擎、本地库接口等组成。

  • 类加载器负责加载类文件。
  • 运行时数据区负责管理内存。
  • 执行引擎负责执行字节码指令和垃圾回收。
  • 本地库接口负责连接其他语言。

http://www.kler.cn/a/573872.html

相关文章:

  • svn 通过127.0.01能访问 但通过公网IP不能访问,这是什么原因?
  • 什么是 JVM? JVM (Java Virtual Machine)
  • 【Elasticsearch】Rollover 操作与Skip Rollover
  • go语言数据类型
  • ESP32-P4 支持哪些 RISC-V 汇编指令?
  • 将 PHP 函数转换为 Python
  • 低空经济-飞行数据平台 搭建可行方案
  • H5DS编辑器是如何让企业快速构建动态页面
  • 【JAVA架构师成长之路】【JDK源码】第5集:Map集合框架与泛型
  • leetcode日记(74)扰乱字符串
  • 科技解密丨赫思嘉·惟愿:深耕医美领域,以创新科技引领行业新篇章
  • DSP笔记
  • 【Aioredis实战总结】如何修改aioredis的最大连接数。
  • 13、TCP和UDP的区别【高频】
  • Linux部署Redis集群
  • 如何用deepseek写游戏(思路教程分享)【附图文】
  • Flink:大数据处理的“双面侠”
  • 【报错:HikariPool-1 - Exception during pool initialization.】
  • Gpt翻译完整版
  • Linux kill 命令