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

打印 上一主题 下一主题

主题 1735|帖子 1735|积分 5205

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

   Java 之所以可以大概实现“一次编写,到处运行”(Write Once, Run Anywhere, WORA),核心在于 Java 虚拟机(JVM, Java Virtual Machine)。JVM 是 Java 程序的运行情况,负责将 Java 字节码(.class 文件)转换成呆板码并执行。
  本文将从 JVM 的基本结构内存管理类加载机制垃圾接纳(GC) 四个方面,初步了解 JVM 的工作原理。
1. JVM 的基本结构

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

  • 类加载子系统

    • 负责加载 .class 文件到内存,并天生对应的 Class 对象。

  • 运行时数据区

    • 包括 方法区(Method Area)堆(Heap)虚拟机栈(VM Stack)本地方法栈(Native Method Stack)程序计数器(Program Counter Register)

  • 执行引擎

    • 负责执行字节码,包括 解释器(Interpreter)即时编译器(JIT Compiler)

  • 本地方法接口

    • 用于调用 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 执行字节码的方式:

  • 解释执行:逐行解释字节码,执行速度较慢。
  • 即时编译(JIT):将热门代码(HotSpot)编译成呆板码,提高执行速度

总结

构成部分核心功能类加载子系统加载 .class 文件到内存运行时数据区存储类信息、对象、方法调用等执行引擎解释或编译执行字节码垃圾接纳(GC)主动接纳无用对象,释放内存 JVM 是 Java 生态的核心,理解其工作原理有助于优化代码、排查内存走漏(OOM)和提升性能。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

千千梦丶琪

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表