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

走进底层 - JVM工作原理入门指南

走进底层 - JVM工作原理入门指南

Java 之所以能够实现“一次编写,到处运行”(Write Once, Run Anywhere, WORA),核心在于 Java 虚拟机(JVM, Java Virtual Machine)。JVM 是 Java 程序的运行环境,负责将 Java 字节码(.class 文件)转换成机器码并执行。

本文将从 JVM 的基本结构内存管理类加载机制垃圾回收(GC) 四个方面,初步了解 JVM 的工作原理。

1. JVM 的基本结构

JVM 主要由以下几个核心部分组成:

  1. 类加载子系统
    • 负责加载 .class 文件到内存,并生成对应的 Class 对象。
  2. 运行时数据区
    • 包括 方法区(Method Area)堆(Heap)虚拟机栈(VM Stack)本地方法栈(Native Method Stack)程序计数器(Program Counter Register)
  3. 执行引擎
    • 负责执行字节码,包括 解释器(Interpreter)即时编译器(JIT Compiler)
  4. 本地方法接口
    • 用于调用 C/C++ 编写的本地库。
      在这里插入图片描述

2. 运行时数据区(内存模型)

JVM 的内存主要分为以下几个部分:

(1) 方法区(Method Area)

  • 用于存储已被加载的类信息、常量、静态变量、即时编译器编译后的代码缓存等数据。在 JDK 8 及之后的版本中,方法区使用元空间(Metaspace)来实现,元空间并不在堆内存中,而是使用本地内存。常量池是方法区的一部分,它存储了各种常量,包括字符串常量、基本数据类型常量等

(2) 堆

  • 所有对象实例和数组都在堆上分配,是垃圾回收(GC)的主要区域,也是jvm的最大区域。
  • 分为:
    • 新生代:存放新创建的对象,分为 Eden 区Survivor 区(S0、S1)
    • 老年代:存放长期存活的对象。
    • 元空间(JDK 8+):取代永久代,存储类元数据。

(3) 虚拟机栈

  • 每个线程在运行时都会有一个对应的 Java 虚拟机栈。它由一个个栈帧(Stack Frame)组成,栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息。当一个方法被调用时,就会创建一个新的栈帧并压入栈顶,方法执行完毕后,栈帧就会从栈顶弹出。局部变量表用于存储方法中的局部变量,包括基本数据类型和对象引用。操作数栈则用于方法执行过程中的运算操作

(4) 本地方法栈

  • 类似于虚拟机栈,但用于执行 本地方法(如 C/C++ 代码)。

(5) 程序计数器

  • 可以理解为一个指针,它记录了当前线程正在执行的字节码指令的地址。如果当前线程正在执行一个 Java 方法,那么程序计数器中保存的就是正在执行的字节码指令的地址;如果正在执行的是本地方法(Native Method),那么程序计数器的值就是未定义的。由于 Java 是多线程的,每个线程都有自己独立的程序计数器,这样当线程切换时,就能够恢复到正确的执行位置

3. 类加载机制

JVM 加载 .class 文件的过程分为 加载、连接、初始化 三个阶段:

(1) 加载(Loading)

  • 通过 类加载器(ClassLoader) 查找 .class 文件并加载到内存。
  • 类加载器分类:
    • Bootstrap ClassLoader(启动类加载器):加载 JAVA_HOME/lib 下的核心类(如 java.lang.*)。
    • Extension ClassLoader(扩展类加载器):加载 JAVA_HOME/lib/ext 下的扩展类。
    • Application ClassLoader(应用类加载器):加载用户类路径(classpath)下的类。
    • 自定义 ClassLoader:用户可继承 ClassLoader 实现自己的加载逻辑。一般用于服务器的加载器(因为同一个类名不会被反复加载,因此为了防止同类名不同数据的类被省略,需要自定义一个类实现多个对象)

(2) 连接

  • 验证:检查字节码是否符合 JVM 规范。
  • 准备:为静态变量分配内存并赋默认值(如 int 默认 0
  • 解析:将符号引用(如 java.lang.Object)替换为直接引用(内存地址),也就是类名等字符转换为地址

(3) 初始化

  • 执行静态代码块(static {})和静态变量赋值。
  • 采用 双亲委派机制 避免重复加载类。

4. 垃圾回收(GC)

JVM 自动管理内存,通过 垃圾回收器 回收不再使用的对象。

(1) 如何判断对象可回收?

  • 引用计数法(Python 使用):对象被引用时计数+1,为 0 时回收(但 Java 不采用,因为无法解决循环引用问题)。
  • 可达性分析:从 GC Roots(如虚拟机栈、静态变量、本地方法栈引用的对象)出发,标记所有可达对象,不可达的视为垃圾。

(2) 垃圾回收算法

  • 标记-清除:标记垃圾对象后直接清除,但会产生内存碎片。
  • 复制:将存活对象复制到另一块内存(用于 新生代,如 Eden → Survivor)。
  • 标记整理:标记存活对象后整理内存(用于 老年代)。

5. 执行引擎

JVM 执行字节码的方式:

  1. 解释执行:逐行解释字节码,执行速度较慢。
  2. 即时编译(JIT):将热点代码(HotSpot)编译成机器码,提高执行速度

总结

组成部分核心功能
类加载子系统加载 .class 文件到内存
运行时数据区存储类信息、对象、方法调用等
执行引擎解释或编译执行字节码
垃圾回收(GC)自动回收无用对象,释放内存

JVM 是 Java 生态的核心,理解其工作原理有助于优化代码、排查内存泄漏(OOM)和提升性能。

相关文章:

  • 大模型备案语料安全要求解析
  • 2025.04.09【Sankey】| 生信数据流可视化精讲
  • LeetcodeBST2JAVA
  • 卡牌收集者1.0
  • JMH 基准测试实战:Java 性能对比的正确打开方式!
  • sqlite3基本语句
  • BUUCTF-web刷题篇(17)
  • Three.js 入门实战:安装、基础概念与第一个场景⭐
  • go语言应该如何学习
  • SQL:JOIN 完全指南:从基础到实战应用
  • EFA-YOLO:一种高效轻量的火焰检测模型解析
  • 【期中准备】电路基础(西电)
  • MySQL事务管理
  • 3 版本控制:GitLab、Jenkins 工作流及分支开发模式实践
  • Kubernetes 深入浅出系列 | 容器剖析之容器安全
  • 链路聚合+vrrp
  • 写给新人的深度学习扫盲贴:ReLu和梯度
  • DocLayout-YOLO:通过多样化合成数据与全局-局部感知实现文档布局分析突破
  • 【Java内存区域有什么?每个区域有什么作用?】
  • 跨站脚本攻击(XSS)与跨站请求伪造(CSRF)的介绍、区别和预防
  • 房地产资讯/如何优化搜索引擎
  • 个人网站设计与开发/美发培训职业学校
  • 网站建设推广公司排名/电话营销系统
  • 佛山哪家网站建设比较好/如何推广自己的产品
  • 苏州建设网站公司/松原头条新闻今日新闻最新
  • 网站开发建设合同/北京网站推广营销服务电话