完整版JVM 深度学习体系(一)

前言

本文档为全网最系统化、无删减、纯干货JVM学习手册,严格按照9大模块编写:JVM架构、运行时数据区、类加载、垃圾回收、字节码与执行引擎、实战调优、工具链、全链路监控、OOM排查。全文适配Java8~Java17,覆盖面试、日常开发、线上故障排查、生产调优,无废话、无删减、可直接保存下载长期学习背诵。

模块一:JVM 整体架构与核心模块

1.1 JVM 定义

JVM(Java Virtual Machine,Java虚拟机):一款抽象的、基于栈式的虚拟机,能够执行Java字节码,屏蔽操作系统底层差异,实现Java跨平台特性。JVM并不局限于Java语言,只要编译为Class字节码的语言(Kotlin、Scala、Groovy)均可运行在JVM之上。

1.2 JVM 整体架构分层

JVM自上而下分为四层架构,完整描述代码从编写到运行的全过程:

  1. 源码层:开发者编写的.java源代码,面向业务逻辑,高级人类可读语言。

  2. 编译层:借助javac前端编译器,将源码编译为平台无关的.class字节码文件,二进制格式,不可直接运行。

  3. 运行层:JVM核心运行环境,包含四大核心模块,负责加载、解析、执行字节码。

  4. 系统层:对接操作系统、CPU、内存、硬件资源,将虚拟机指令翻译为本地硬件指令。

1.3 JVM 四大核心模块(必考)

JVM运行层由四大核心子系统构成,互相配合完成程序运行,是JVM最底层骨架:

1.3.1 类加载子系统

负责读取外部Class字节码文件,加载至JVM内存,生成java.lang.Class对象;完成类的验证、准备、解析、初始化,管控类的整个生命周期。

1.3.2 运行时数据区

JVM内存模型,程序运行时所有数据的存储载体。包含线程私有内存与线程共享内存,是对象、变量、方法执行的内存基础,也是GC、OOM问题的核心区域。

1.3.3 执行引擎

JVM的CPU,负责翻译并执行字节码指令。包含解释器、JIT即时编译器、垃圾回收器,是代码真正执行的核心模块。

1.3.4 本地方法接口(JNI)

打通Java与底层C/C++的桥梁,用于调用操作系统底层资源。Java中标记native的方法均由该模块执行,例如线程、IO、内存操作底层方法。

1.4 跨平台与字节码设计思想

1.4.1 跨平台本质

核心口号:一次编译,到处运行

原理:Java源码仅编译一次生成统一格式的Class字节码,不同操作系统安装对应适配版本的JVM;由JVM屏蔽Windows、Linux、Mac系统指令差异,统一解析执行字节码。

1.4.2 字节码设计思想

  1. 中立性:不属于任何操作系统、CPU架构;

  2. 精简性:指令短小、文件体积小,加载速度快;

  3. 通用性:多语言编译为字节码,实现语言无关性;

  4. 可移植性:任意装有JVM的设备均可运行。

1.5 虚拟机架构分类

1.5.1 基于栈式虚拟机(HotSpot JVM)

执行计算依赖虚拟机内部操作数栈,无硬件寄存器绑定。

优点:跨平台极强、指令简单、移植性好;缺点:执行速度略慢。

1.5.2 基于寄存器式虚拟机

模拟物理CPU寄存器,直接在寄存器中运算。

优点:执行效率高、运算速度快;缺点:平台耦合度高、移植差。代表:Lua、ART。

1.5.3 混合架构虚拟机

结合栈式跨平台优势与寄存器高效执行优势,新版ZGC、OpenJDK均采用混合优化架构。

模块二:运行时数据区(堆、栈、方法区完整版解析)

2.1 内存区域整体划分

2.1.1 线程私有内存(生命周期跟随线程、无GC)

线程私有区域,线程创建分配、线程销毁释放,不存在垃圾回收。包含:程序计数器、虚拟机栈、本地方法栈。

2.1.2 线程共享内存(全局共享、GC管控)

进程级别共享,所有线程均可访问,存在GC回收。包含:Java堆、方法区、运行时常量池、直接内存。

2.2 线程私有区域详解

2.2.1 程序计数器(唯一无OOM区域)

  1. 作用:记录当前线程正在执行的字节码行号;

  2. 特性:线程私有、内存极小、无GC、永远不会发生内存溢出

  3. 使用场景:线程切换后恢复执行位置。

2.2.2 Java虚拟机栈(Java Stack)

  1. 存储内容:每一个方法调用对应一个栈帧

  2. 栈帧组成:局部变量表、操作数栈、动态链接、方法返回地址、附加信息;

  3. 异常类型:

    1. StackOverflowError:栈深度过大(递归死循环);

    2. OOM:不断扩容导致栈内存耗尽;

  4. 生命周期:方法调用入栈,方法执行完毕自动出栈销毁。

2.2.3 本地方法栈

专门服务于Native本地方法,执行C/C++底层代码;异常类型、内存结构与虚拟机栈一致。

2.3 线程共享区域详解

2.3.1 Java堆(Heap,GC主战场)

  1. 存储内容:所有对象实例、数组,唯一存放对象的内存区域;

  2. 内存分区:新生代 + 老年代;

  3. 分区比例:Eden:S0:S1 = 8:1:1;

  4. 区域作用:

    1. Eden区:新建对象存放位置;

    2. Survivor区:存活对象中转、筛选长期存活对象;

    3. 老年代:存放存活时间久、大体积对象;

  5. 调控参数:-Xms、-Xmx、-Xmn;

  6. 溢出异常:Java heap space。

2.3.2 方法区(JDK8永久代→元空间)

  1. 存储内容:类元信息、常量、静态变量、即时编译代码、方法结构;

  2. 版本演变:

    1. JDK1.6及之前:永久代(堆内内存);

    2. JDK1.8:彻底删除永久代,改为元空间Metaspace(本地物理内存)

  3. 溢出场景:大量动态代理、CGLIB生成类、频繁加载Class;

  4. 异常:Metaspace。

2.3.3 运行时常量池

隶属于方法区,存放编译期生成的字面量、符号引用;运行期间可动态放入常量。

2.3.4 直接内存(堆外内存)

  1. 不属于JVM运行时数据区,不受堆内存限制;

  2. 使用场景:NIO、Netty、零拷贝;

  3. 优点:读写速度快、减少内存拷贝;

  4. 异常:Direct buffer memory。

2.4 所有内存区域异常汇总表

  • 程序计数器:无异常;

  • 虚拟机栈:StackOverflowError、栈OOM;

  • 堆:Java heap space;

  • 元空间:Metaspace;

  • 直接内存:Direct buffer memory。

模块三:类加载子系统(5阶段、双亲委派、自定义加载器)

3.1 类完整生命周期(7阶段)

加载 → 验证 → 准备 → 解析 → 初始化 → 使用 → 卸载。

3.2 五大核心加载阶段(重点)

3.2.1 加载阶段

读取磁盘Class二进制文件,加载到内存;在方法区生成Class类对象,保存类结构信息。

3.2.2 验证阶段(安全校验)

四层校验:文件格式验证、元数据验证、字节码验证、符号引用验证;防止恶意字节码破坏虚拟机。

3.2.3 准备阶段

静态变量 分配内存,赋默认初始值(int=0、boolean=false、引用=null),不赋值开发者自定义值。

3.2.4 解析阶段

将代码中的符号引用 (字符串格式)替换为直接内存引用(真实内存地址),为执行做准备。

3.2.5 初始化阶段(唯一主动触发阶段)

执行静态代码块、给静态变量赋予开发者自定义初始值;触发条件:new对象、访问静态方法/静态变量、反射、子类初始化、启动主类。

3.3 四层类加载器层级

  1. 启动类加载器(Bootstrap):C++编写,加载JDK核心依赖rt.jar;

  2. 平台类加载器(Platform):加载系统扩展包;

  3. 应用类加载器(System/App):加载开发者自定义项目类;

  4. 自定义类加载器:开发者手动实现,实现个性化加载逻辑。

3.4 双亲委派模型(面试必考)

3.4.1 执行规则

当类加载器收到加载请求,优先向上委托父加载器加载;父加载器无法加载,自身才加载。加载顺序:启动类加载器→平台→应用→自定义。

3.4.2 核心作用

  1. 安全防护:防止恶意篡改核心类(例如篡改String类);

  2. 类唯一性:保证全局同一个类只加载一次;

  3. 层级隔离:划分系统类与自定义类。

3.4.3 破坏双亲委派三大场景

  1. SPI机制:JDBC驱动;

  2. Tomcat容器:实现Web应用类隔离;

  3. 热部署、热加载:动态替换Class。

3.5 自定义类加载器

3.5.1 实现方式

继承ClassLoader,重写findClass方法,自定义读取Class字节码逻辑。

3.5.2 实战用途

  • Class文件加密解密;

  • 代码热部署、不停机更新;

  • 依赖包隔离、避免类冲突。

模块四:垃圾回收机制(算法、收集器、分代策略)

4.1 对象存活判定方式

4.1.1 引用计数法(废弃)

给对象添加引用计数器,引用+1、失效-1;计数器为0判定回收。缺陷:无法解决循环引用,现代JVM废弃。

4.1.2 可达性分析法(HotSpot主流)

GC Roots为起始节点,向下遍历引用链;不可到达的对象判定为垃圾对象。

4.1.3 可作为GC Roots的对象

  • 虚拟机栈中引用的对象;

  • 静态变量引用对象;

  • 常量引用对象;

  • 本地方法栈Native引用对象。

4.2 Java四大引用体系

  1. 强引用:默认引用,只要引用存在,永远不回收;

  2. 软引用:内存充足不回收,内存不足强制回收;适用缓存;

  3. 弱引用:只要发生GC,必定回收;适用临时缓存;

  4. 虚引用:无引用效果,仅用于监控GC回收状态。

4.3 三大基础垃圾回收算法

4.3.1 标记-清除算法

标记垃圾、统一清除;优点:简单;缺点:产生大量内存碎片、分配效率低。

4.3.2 标记-复制算法

划分同等大小内存,存活对象复制到空闲区域,清空原区域;优点:无内存碎片;缺点:内存直接浪费一半。适用于新生代。

4.3.3 标记-整理算法

标记垃圾、清除后压缩整理内存,存活对象向一端移动;优点:无碎片;缺点:移动成本高。适用于老年代。

4.4 分代收集策略(JVM核心)

  1. 新生代 :对象朝生夕死、存活率极低 → 标记复制算法

  2. 老年代 :对象存活久、存活率高 → 标记清除/标记整理

4.5 主流垃圾收集器大全(对比+适用场景)

4.5.1 新生代收集器

  • Serial:单线程收集、客户端使用、内存小;

  • ParNew:多线程版本Serial,唯一适配CMS;

  • Parallel Scavenge:高吞吐量、后台任务、大数据使用。

4.5.2 老年代收集器

  • Serial Old:单线程老年代收集;

  • Parallel Old:配合Parallel,高吞吐量;

  • CMS:并发低延迟、互联网Web服务、存在内存碎片。

4.5.3 全堆统一收集器(现代主流)

  • G1:分区收集、可预测停顿、JDK9默认、均衡吞吐量与延迟;

  • ZGC:毫秒级超低延迟、超大堆、JDK11+;

  • Shenandoah:开源低延迟收集器。

4.6 GC分类

  • Minor GC:新生代GC、频率高、速度快;

  • Major GC:老年代GC、速度慢;

  • Full GC:全堆+元空间统一回收、耗时极长、线上严禁频繁触发。

模块五:字节码与执行引擎(结构、指令、JIT优化)

5.1 Class字节码文件结构

Class文件为二进制字节流,固定顺序结构:

  1. 魔数:固定0xCAFEBABE,标识Class文件;

  2. 版本号:主次版本,标识JDK编译版本;

  3. 常量池:占用空间最大,存放字符串、符号引用;

  4. 访问标识:标识类、修饰符、权限;

  5. 类索引、父类索引、接口索引;

  6. 字段表:成员变量、静态变量;

  7. 方法表:方法字节码、异常、参数;

  8. 属性表:附加信息,注解、代码行号。

5.2 常用字节码指令

  • 栈操作指令:入栈、出栈;

  • 运算指令:加减乘除、位运算;

  • 跳转指令:if、for、while循环跳转;

  • 对象指令:new、instanceof;

  • 方法调用指令:invokestatic、invokevirtual。

5.3 JVM三大执行引擎

5.3.1 解释器

逐行翻译字节码、边解释边执行;启动速度快、运行速度慢,适合少量代码。

5.3.2 JIT即时编译器(核心优化)

监测热点代码,将高频执行字节码编译为本地机器码,缓存复用,运行速度极快。

  • C1编译器:客户端编译、快速简单优化;

  • C2编译器:服务端编译、深度复杂优化。

5.3.3 混合执行模式

JVM默认模式:解释执行 + JIT编译结合,兼顾启动速度与运行效率。

5.4 JIT五大核心优化手段

  1. 逃逸分析:判断对象是否逃出方法作用域;

  2. 栈上分配:未逃逸对象分配至栈,不占用堆内存;

  3. 标量替换:拆解对象为基础数据,取消对象创建;

  4. 方法内联:合并短小方法,减少调用开销;

  5. 同步消除:去除无竞争锁,优化同步开销。

5.5 JMM Java内存模型

5.5.1 并发三大特性

原子性、可见性、有序性。

5.5.2 volatile关键字

保证可见性、禁止指令重排序;不保证原子性;底层依靠内存屏障实现。

5.5.3 Happens-Before先行发生原则

八大规则,判定多线程内存可见性,无需开发者手动加锁。

模块六:实战调优(参数配置+案例分析)

6.1 核心JVM内存参数

复制代码

-Xms:堆初始内存 -Xmx:堆最大内存(生产必须 Xms=Xmx) -Xmn:新生代内存大小 -XX:SurvivorRatio:伊甸区比例 -XX:MetaspaceSize:元空间初始值 -XX:MaxMetaspaceSize:元空间上限 -XX:MaxDirectMemorySize:直接内存上限

6.2 主流收集器启用参数

复制代码

-XX:+UseConcMarkSweepGC 启用CMS -XX:+UseG1GC 启用G1(JDK9默认) -XX:+UseZGC 启用ZGC(JDK11+) -XX:+PrintGCDetails 打印详细GC日志

6.3 调优三大核心目标

  1. 高吞吐量:大数据、定时任务 → Parallel收集器;

  2. 低延迟:互联网接口、高并发服务 → G1/ZGC;

  3. 通用原则:严控FullGC、减少GC停顿、控制内存占用。

6.4 线上实战调优案例

6.4.1 微服务小堆调优

限制堆内存、使用G1、降低元空间大小,减少资源占用。

6.4.2 定时任务频繁GC优化

增大新生代、提高吞吐量、减少对象晋升老年代。

6.4.3 高并发接口卡顿优化

更换ZGC、降低停顿时间、优化内存屏障。

模块七:JVM工具链(命令行+可视化+Arthas+MAT)

7.1 JDK自带命令行工具(必备)

  1. jps:查看Java进程、进程ID、启动参数;

  2. jstat:实时监控GC次数、占用、类加载、编译统计;

  3. jmap:查看堆内存对象分布、dump堆快照;

  4. jstack:排查线程死锁、CPU飙高、线程阻塞;

  5. jinfo:动态查看、修改虚拟机运行参数;

  6. jcmd:全能命令,整合所有工具功能。

7.2 基础可视化工具

  • JConsole:简易监控、免费、基础指标查看;

  • JVisualVM:全能可视化,监控内存、线程、GC、导出快照。

7.3 线上诊断神器:Arthas(阿里)

生产环境无停机、无侵入诊断工具,企业必备。

  • 查看方法执行耗时、追踪调用链路;

  • 动态查看运行时参数、返回值;

  • 热更新代码、无需重启服务;

  • 监控线程、内存、GC实时状态。

7.4 内存泄漏专用:MAT

专业分析dump堆快照,定位内存泄漏。

  • 统计大对象、冗余对象;

  • 分析对象引用链,找出泄漏源头;

  • 生成泄漏报表、风险提示。

模块八:性能监控(全链路监控方案)

8.1 核心监控指标

8.1.1 内存指标

堆内存使用率、元空间占用、直接内存占用、内存波动。

8.1.2 GC指标

MinorGC次数、FullGC次数、GC停顿耗时、GC吞吐量。

8.1.3 线程指标

活跃线程、阻塞线程、等待线程、死锁线程、峰值线程数。

8.1.4 类加载指标

加载类数量、卸载类数量、元空间增长速率。

8.2 企业级监控架构

SpringBoot + Actuator + Prometheus + Grafana

  1. Actuator:暴露JVM监控端点;

  2. Prometheus:时序数据存储、指标采集;

  3. Grafana:可视化大屏、曲线图、仪表盘。

8.3 线上告警策略

  • 堆内存使用率超过80%告警;

  • 1小时出现多次FullGC告警;

  • 线程阻塞、死锁告警;

  • 元空间持续上涨告警。

模块九:OOM内存溢出(全场景分析+排查流程)

9.1 八大OOM全场景详解

  1. Java heap space:堆内存溢出,大量对象、内存泄漏;

  2. Metaspace:动态类过多、代理频繁、类未卸载;

  3. Direct buffer memory:NIO堆外内存未释放;

  4. StackOverflow:递归死循环、方法嵌套过深;

  5. 无法创建新线程:线程池无限创建、线程无销毁;

  6. 超大数组OOM:一次性申请超大连续内存;

  7. 本地内存溢出:系统物理内存耗尽;

  8. 容器限制OOM:Docker环境内存配额不足。

9.2 高频内存泄漏原因

  • 静态集合长期持有引用;

  • 线程池线程常驻不销毁;

  • 监听器、回调方法未注销;

  • IO流、连接池资源未关闭;

  • 缓存无过期淘汰策略。

9.3 线上标准排查流程(企业通用)

  1. 查看日志,判定OOM异常类型;

  2. jstat持续观察内存、GC走势;

  3. jstack排查线程死锁、阻塞;

  4. jmap导出dump堆快照;

  5. MAT分析引用链、定位泄漏对象;

  6. 代码溯源、修复bug;

  7. 压力测试、验证修复效果。

附录:JVM高频面试总结

  1. 简述JVM四大核心模块?

  2. 运行时数据区划分、各区域作用?

  3. 双亲委派模型原理、作用、破坏场景?

  4. GC可达性分析、GC Roots包含哪些?

  5. CMS、G1、ZGC区别与适用场景?

  6. JIT优化包含哪些手段?

  7. 线上OOM排查完整流程?

  8. 生产环境JVM调优原则?

  9. 内存泄漏与内存溢出区别?

  10. volatile底层原理、内存屏障?

相关推荐
就改了19 小时前
Java8 日期处理(详细版)
java·python·算法
麻瓜生活睁不开眼20 小时前
Android16定制SearchLauncher新增投屏Cast桌面快捷图标完整实现
java·launcher·aosp16
IT小盘21 小时前
12-Prompt不等于一句话-System-User-Context三层结构
java·windows·prompt
都叫我大帅哥1 天前
Spring Data JPA 查询之道:方法命名与示例查询完全指南
java·后端·spring
momo1 天前
Java+WebAI黑马知识点
java·spring boot·mybatis
重庆小透明1 天前
带你从不同视角了解三大MQ
java·学习·spring·kafka·rabbitmq·rocketmq
冰心孤城1 天前
C++ 与 C#混合编程 示例 (基于VS)
java·c++·c#
风中芦苇啊1 天前
Java EasyExcel 导入通用工具类:自定义注解映射字段 + 反射机制
java·开发语言
家有娇妻张兔兔1 天前
Java 对接 PLC 主流型号最合适的方案:Apache PLC4X 实战指南
java·开发语言·plc·modbus·数据缓存·西门子s7·apache plc4x
独行侠影a1 天前
Rust vs. Zig:2026年系统编程语言的“双雄争霸”,谁更适合替代C++?
java·开发语言