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

Java核心 之JVM

JVM(Java Virtual Machine,Java 虚拟机)是 Java 语言跨平台特性的核心,它负责将字节码(.class 文件)解释或编译为机器码并执行。以下从核心角度详解 JVM:

一、JVM 的作用与地位

  1. 跨平台基石:"一次编写,到处运行"(Write Once, Run Anywhere)的实现者,通过屏蔽不同操作系统的底层差异,使字节码在任何安装了 JVM 的平台上运行。
  2. 内存管理:自动负责内存分配与回收(垃圾回收),减少手动内存操作的风险。
  3. 执行引擎:将字节码转换为机器码(解释执行或即时编译 JIT)。

二、JVM 内存结构(基于 Java 8 及以后)

JVM 内存分为线程私有线程共享两大区域:

1. 线程私有区域(随线程创建 / 销毁)
  • 程序计数器(Program Counter Register)记录当前线程执行的字节码指令地址(如分支、循环、跳转等),是唯一不会 OOM 的区域。

  • 虚拟机栈(VM Stack)存储方法调用的栈帧(Stack Frame),每个栈帧包含:

    • 局部变量表(方法内变量)
    • 操作数栈(计算过程的临时数据)
    • 动态链接(指向常量池的引用)
    • 方法返回地址可能抛出StackOverflowError(栈深度溢出)、OutOfMemoryError(栈扩展失败)。
  • 本地方法栈(Native Method Stack)类似虚拟机栈,但为 Native 方法(如 C/C++ 实现的方法)服务,HotSpot 将其与虚拟机栈合并实现。

2. 线程共享区域(随 JVM 启动 / 关闭)
  • 堆(Heap)

    • JVM 中最大的内存区域,所有对象实例及数组均在此分配。
    • 是垃圾回收(GC)的主要区域,可分为:
      • 新生代(Eden 区 + 两个 Survivor 区,比例通常 8:1:1)
      • 老年代(存放存活久的对象)可能抛出OutOfMemoryError: Java heap space
  • 方法区(Method Area)

    • 存储类信息(结构、方法、字段)、常量、静态变量、即时编译后的代码等。
    • Java 8 后由元空间(Metaspace) 实现,取代永久代,元空间使用本地内存,默认无上限(可配置)。可能抛出OutOfMemoryError: Metaspace(元空间不足)。
  • 运行时常量池(Runtime Constant Pool)

    • 方法区的一部分,存放类加载时从字节码常量池解析出的字面量(如字符串)和符号引用(如类名、方法名)。
    • 字符串常量池(String Pool)是其重要组成,JDK 7 后移至堆中。

三、类加载机制

JVM 将.class 文件加载到内存并生成可执行代码的过程,分为 5 步:

  1. 加载(Loading)通过类全限定名(如java.lang.String)获取二进制字节流,将其转换为方法区的运行时数据结构,并在堆中生成Class对象作为访问入口。

  2. 验证(Verification)确保字节码符合 JVM 规范(如格式正确、安全校验),防止恶意字节码攻击。

  3. 准备(Preparation)为类的静态变量分配内存并设置初始默认值(如int为 0,boolean为 false),不包含初始化语句(如static int a = 10中的 10 在初始化阶段赋值)。

  4. 解析(Resolution)将常量池中的符号引用(如类名、方法名)替换为直接引用(内存地址)。

  5. 初始化(Initialization)执行类构造器<clinit>()方法:

    • 合并静态变量赋值语句和静态代码块(按顺序执行)。
    • 父类<clinit>()先于子类执行。

四、垃圾回收(GC)

JVM 自动回收不再被引用的对象内存,核心步骤:

1. 如何判断对象可回收?
  • 引用计数法:对象被引用时计数 + 1,失效时 - 1,计数为 0 则可回收(缺点:无法解决循环引用)。
  • 可达性分析:以 "GC Roots" 为起点(如虚拟机栈引用的对象、静态变量、常量等),不可达的对象标记为可回收。
2. 垃圾回收算法
  • 标记 - 清除(Mark-Sweep):标记可回收对象后直接清除(缺点:产生内存碎片)。
  • 标记 - 复制(Mark-Copy):将存活对象复制到新区域,清除原区域(适合新生代,如 Eden 区到 Survivor 区)。
  • 标记 - 整理(Mark-Compact):标记后将存活对象向一端移动,再清除边界外内存(适合老年代)。
3. 常见垃圾收集器
  • SerialGC:单线程 GC,适用于简单应用(Client 模式)。
  • ParallelGC:多线程 GC,注重吞吐量(吞吐量 = 运行用户代码时间 / 总时间)。
  • CMS(Concurrent Mark Sweep):并发标记清除,注重低延迟(停顿时间短)。
  • G1(Garbage-First):将堆分为多个 Region,优先回收垃圾多的区域,平衡吞吐量和延迟(Java 9 后默认)。
  • ZGC/Shenandoah:超低延迟 GC(毫秒级以下),适合大内存场景。

五、执行引擎

将字节码转换为机器码的核心组件:

  1. 解释器:逐行解释字节码为机器码,启动快但执行慢。
  2. JIT 编译器(即时编译器):将热点代码(频繁执行的代码)编译为本地机器码缓存,提高执行效率(HotSpot 的 C1 编译器针对客户端,C2 针对服务端)。
  3. 混合模式:JVM 默认采用解释 + JIT 编译结合的方式,兼顾启动速度和执行效率。

六、JVM 参数调优

通过 JVM 参数配置内存大小、GC 策略等,常见参数:

  • 堆内存:-Xms(初始堆大小)、-Xmx(最大堆大小,建议与-Xms一致避免频繁扩容)。
  • 新生代:-Xmn(新生代大小)、-XX:SurvivorRatio=8(Eden 与 Survivor 比例)。
  • 元空间:-XX:MetaspaceSize-XX:MaxMetaspaceSize
  • GC 日志:-XX:+PrintGCDetails-XX:+PrintGCTimeStamps(分析 GC 问题)。
  • 垃圾收集器:-XX:+UseG1GC(使用 G1)、-XX:+UseZGC(使用 ZGC)。

总结

JVM 是 Java 生态的核心,其内存管理、类加载、垃圾回收和执行引擎共同支撑了 Java 的跨平台性和安全性。理解 JVM 原理不仅有助于排查内存泄漏、OOM 等问题,也是高性能 Java 应用调优的基础。

http://www.dtcms.com/a/410015.html

相关文章:

  • 通过 GAC Code 在国内使用ClaudeCode,Windows 用户配置指南!
  • iOS App 上架流程详解,苹果应用发布步骤、App Store 审核规则、ipa 文件上传与测试分发实战经验
  • 线程安全之《Sychronized的八锁案例》
  • 用户态的epoll实现思路?
  • TextMeshPro文字消失bug解决方案
  • 学习网站开发教程wordpress 五分钟
  • 联邦学习中的异质性问题
  • 将照片从iPhone传输到联想笔记本的6种方法
  • 东莞网站设计找哪里易商官方网站
  • 本机可以做网站的服务器互联斗士网站建站
  • 基于 GitLab 的自动化镜像构建
  • Spark核心Shuffle详解(一)ShuffleManager
  • Android 开发环境解析:从SDK、NDK到版本兼容性指南
  • 基于YOLO8+flask+layui的行人跌倒行为检测系统【源码+模型+数据集】
  • Mysql DBA学习笔记(日志)
  • 平替MongoDB:金仓多模数据库助力电子证照国产化实践
  • QT6中QGraphicsView功能与应用
  • WSL2搭建Hadoop伪分布式环境
  • 新闻媒体发稿平台排名Top5,聚合型新闻发稿服务平台推荐
  • Linux(4)|入门的开始:Linux基本指令(4)
  • (七)API 重构的艺术:打造优雅、可维护的 API
  • MAC idea 环境变量设置失效
  • 百度站长收录提交入口深圳设计网站源码
  • 2025Unity超详细《坦克大战3D》项目实战案例(上篇)——UI搭建并使用和数据持久化(附资源和源代码)
  • DenseNet:密集连接
  • 第一次学习Hardhat
  • 腾讯wordpress 建站自适应网站建设哪家便宜
  • 第八章 MyBatis及MyBatis-Plus
  • 5mins了解redis底层数据结源码
  • 华为云学习笔记(四):运维类服务与企业网站上云实践