全网最通俗易懂 JVM 入门教程:从原理到实战,新手也能秒懂
前言
很多 Java 初学者学会了基础语法、面向对象,却始终搞不懂我们写的 Java 代码到底是怎么跑起来的,也不明白为什么 Java 能称霸企业级开发,更不知道线上内存溢出、卡顿该怎么解决。
这篇文章不讲晦涩理论,全程大白话 + 实战,带你吃透 JVM 核心知识点:Java 代码执行流程、跨平台原理、JDK/JRE/JVM 区别、运行时数据区、垃圾回收、类加载、JVM 调优、可视化工具。
不管是面试、期末复习,还是解决实际生产问题,这一篇就够了!
一、灵魂 4 问:搞懂 JVM 的前提
1. 我们写的 Java 代码,电脑是怎么认识的?
电脑只认识二进制 0/1,完全看不懂我们写的HelloWorld.java。
Java 代码执行流程(必须背下来):
- 程序员编写
.java源文件(人能看懂,电脑看不懂) - 使用
javac编译器 → 编译成 .class 字节码文件(JVM 能看懂) - JVM 类加载器加载字节码
- 执行引擎将字节码 → 编译成机器码(电脑最终能看懂并运行)
一句话总结:Java 文件 → 编译成 Class 文件 → JVM 识别 → 翻译成机器指令 → 电脑运行
2. 为什么说 Java 是跨平台语言?一次编写,到处运行?
核心答案:因为有 JVM 虚拟机。
- Windows、Linux、Mac 系统都有对应的 JVM
- JVM 屏蔽了底层操作系统、硬件的差异
- 我们只需要生成一份
.class文件,在任何安装了 JVM 的机器上都能跑
对比 C/C++:C/C++ 是直接编译成对应系统的机器码,换系统必须重新编译,代码还可能不兼容。
3. JDK、JRE、JVM 到底有什么区别?(面试高频)
一句话包含关系:JDK > JRE > JVM
- JVM:Java 虚拟机,真正运行 Java 代码的地方
- JRE:Java 运行环境 = JVM + 核心类库(C/C++ 编写)
- JDK:Java 开发工具包 = JRE + 编译工具 (javac) + 监控工具 + 调试工具
✅ 总结:
- 运行 Java 程序:装 JRE 就行
- 开发 Java 程序:必须装 JDK
4. 我们为什么要学习 JVM?
Java 自带自动内存管理、自动垃圾回收,开发时几乎不用管内存,那为什么还要学?
两个最真实的理由:
- 线上出问题你得会排查内存溢出 (OOM)、内存泄漏、频繁 GC 导致卡顿、服务崩溃
- 项目性能优化必须会 JVM高并发下调优、减少停顿、提升吞吐量
就像人不用管食物怎么消化,但生病了必须去医院。
二、JVM 核心:运行时数据区(内存模型)
JVM 运行时,数据都存在哪里?这是 JVM 最重要的知识点。
五大区域划分
- 程序计数器(线程私有)
- 虚拟机栈(线程私有)
- 本地方法栈(线程私有)
- 堆内存(线程共享)
- 方法区(线程共享)
2.1 程序计数器
- 作用:记录当前线程执行到哪一行字节码指令
- 特点:线程私有、不会 OOM、很小
- 场景:线程切换后能恢复到正确执行位置(CPU 时间片切换)
2.2 Java 虚拟机栈(最常考)
- 线程私有,生命周期和线程一致
- 每个方法执行 → 创建一个 栈帧
- 栈帧内部构成:
- 局部变量表:存放基本类型、对象引用
- 操作数栈:计算、操作数据
- 动态链接:方法调用跳转
- 方法出口:return / 异常
高频面试题:
- 方法调用方法:会创建多个栈帧
- 递归调用:会一直压栈 → 太深会栈溢出 StackOverflowError
- 栈指向堆:栈里存对象引用地址,真实对象在堆里
2.3 本地方法栈
- 管理
native方法(底层 C/C++ 代码) - 例如:
Thread.start()底层调用 native 方法
2.4 Java 堆(Heap)—— JVM 最大的一块内存
所有对象、数组都在堆上分配!
特点:
- 线程共享
- GC 垃圾收集器主要管理区域(GC 堆)
- 可动态扩展,不足抛出 OOM 内存溢出
堆内存划分(分代回收):
- 新生代 (1/3):Eden : From : To = 8:1:1
- 老年代 (2/3)
2.5 方法区
- 线程共享
- 存储:类信息、常量、静态变量、即时编译代码
- JDK8 以后叫 元空间 (Metaspace)
三、直接内存 & 执行引擎 & 垃圾回收系统
3.1 直接内存(堆外内存)
不属于 JVM 运行时数据区,但 NIO 大量使用。
堆内存 VS 直接内存
- 分配速度:堆内存 > 直接内存
- 读写速度:直接内存 >>> 堆内存
- 使用场景:频繁 IO 读写(网络、文件)
3.2 JVM 执行引擎
把 .class 字节码 → 翻译成 机器码,让 CPU 执行。
3.3 垃圾收集系统(GC)
Java 最强大的能力:自动回收垃圾,不用手动 free。
四、JVM 垃圾回收机制(GC)全网最通俗讲解
4.1 什么是垃圾?
没有任何引用指向的对象,就是垃圾,需要被回收。
4.2 如何判断对象可以回收?
① 引用计数法(JVM 不采用)
- 每个对象有个计数器
- 有引用 + 1,引用删除 - 1
- 为 0 就回收
- 致命缺点:无法解决循环引用
② 可达性分析算法(JVM 采用)
从 GC Roots 往下找,找不到引用链 → 判定为垃圾。
可作为 GC Roots 的对象:
- 虚拟机栈中引用的对象
- 静态变量引用的对象
- 常量引用的对象
- 本地方法栈引用的对象
4.3 垃圾回收算法
1)复制算法
- 把存活对象复制到空区域
- 优点:速度快、无碎片
- 适用:新生代
2)标记 - 清除算法
- 先标记垃圾,再清除
- 缺点:效率低、产生内存碎片
- 适用:老年代
3)标记 - 整理算法
- 标记后把存活对象挪到一起,清除边界外内存
- 优点:无内存碎片
- 适用:老年代
4)分代收集算法(JVM 默认使用)
- 新生代:对象朝生夕死 → 用复制算法
- 老年代:对象存活久 → 用标记清除 / 标记整理
4.4 堆内存分代与 GC 类型
- Minor GC:新生代 GC,频繁、速度快
- Major GC:老年代 GC,慢
- Full GC:整堆回收,最慢,尽量避免
对象晋升老年代条件:
- 年龄默认 15 岁
- 大对象直接进老年代
五、7 种垃圾收集器(JDK8 必考)
表格
| 收集器 | 区域 | 算法 | 特点 |
|---|---|---|---|
| Serial | 新生代 | 复制 | 单线程、简单 |
| ParNew | 新生代 | 复制 | 多线程、配合 CMS |
| ParallelGC | 新生代 | 复制 | 吞吐量优先 |
| SerialOld | 老年代 | 标记整理 | 单线程 |
| ParallelOld | 老年代 | 标记整理 | 多线程、吞吐量 |
| CMS | 老年代 | 标记清除 | 低停顿 |
| G1 | 整堆 | 混合 | JDK9 默认、服务端首选 |
六、JVM 常用参数配置(生产环境必备)
最核心内存参数
-Xms 初始堆大小
-Xmx 最大堆大小(生产环境建议和Xms一样大)
-Xmn 新生代大小
-Xss 线程栈大小
-XX:NewRatio 新生代:老年代 默认 1:2
-XX:SurvivorRatio Eden:Suvivor 默认8:1:1
GC 收集器设置
-XX:+UseSerialGC 串行
-XX:+UseParNewGC 并行新生代
-XX:+UseParallelGC 吞吐量优先
-XX:+UseConcMarkSweepGC CMS
-XX:+UseG1GC G1收集器
JVM 参数在哪里配置?
- IDEA:Run Configuration → VM options
- Tomcat:catalina.sh/bat 配置 JAVA_OPTS
- SpringBoot Jar:
java -Xms512m -Xmx512m -jar xxx.jar
七、类加载机制与双亲委派模型
7.1 类加载过程
- 加载:读取 class 文件到内存
- 验证:检查安全性
- 准备:静态变量分配内存
- 解析:符号引用转直接引用
- 初始化:执行静态代码块、静态变量赋值
7.2 四种类加载器
- 启动类加载器(C++):加载核心类 rt.jar
- 扩展类加载器:加载 ext 目录
- 应用类加载器:加载我们自己写的类
- 自定义类加载器
7.3 双亲委派模型(面试必问)
工作原理:子类加载器接到任务 → 交给父类 → 一直传到启动类加载器父类能加载就加载,不能加载才自己加载。
优点:
- 避免类重复加载
- 沙箱安全:防止核心 API 被篡改(比如自己写 java.lang.Integer)
八、JVM 可视化监控工具
1. VisualVM
JDK 自带,最强免费 JVM 分析工具
- 监控内存
- 查看 GC
- 分析 CPU 占用
- 排查内存泄漏
位置:JDK/bin/jvisualvm.exe
2. JConsole
简单轻量监控工具。
九、总结(背会这一段应付面试)
- Java 代码 → .java → javac → .class → JVM → 机器码
- JDK 包含 JRE,JRE 包含 JVM
- JVM 内存 = 栈 (线程私有) + 堆 (共享,存对象) + 方法区 + 计数器 + 本地方法栈
- GC 使用可达性分析,分代回收:新生代复制算法,老年代标记整理 / 清除
- 垃圾收集器:JDK8 默认 Parallel,推荐 G1
- 类加载遵循双亲委派,保证安全和不重复加载
- JVM 用来排查 OOM、GC 频繁、性能瓶颈
更多推荐



所有评论(0)