大家好,我是程序员柏风,AI 最全的 Vibecoding 学习地图 http://coderoadmap.cn 作者。
Java 与 JVM 是什么
这一课你将能做到
- 用一张图说清楚 JDK、JRE、JVM 各自负责什么,以及
.java从源码到运行经过了哪些环节 - 在本机确认已安装 JDK 17+,并用一条命令跑通第一个 Java 程序
- 说出本站后端(Spring Boot + MySQL + Redis)为什么选 Java,以及「编译一次、到处运行」对部署意味着什么
为什么要学
本站的后端 API 跑在 Spring Boot 上:请求先到 Controller,业务逻辑在 Service,数据存 MySQL,热点数据放缓存 Redis。这些 .java 源文件不是直接交给 CPU 执行的——它们先被编译成字节码,再由 JVM(Java 虚拟机) 执行。
人话:你写的 Java 代码像一份「国际通用剧本」,JVM 是部署在 Windows、Linux、macOS 上的「剧团」,负责把同一份剧本演成本机动作。你以后开发、部署、排错时遇到的「找不到主类」「JDK 版本不对」「编译失败」,全都能在这一层找到根源。不理解 JVM 这一环,问题就只能靠猜。
先建立图像
你写的 .java 文件
│ javac(编译器,在 JDK 里)
▼
.class 字节码(平台无关的中间码)
│ java 命令启动 JVM
▼
JVM 执行:解释执行 + JIT 把热点代码编译成本机指令
│
▼
内存由 JVM 管理:分配对象、垃圾回收(GC)
三个名字的关系:
| 名字 | 人话 | 你日常碰到 |
|---|---|---|
| JVM | 执行字节码的虚拟机 | 管内存、线程、GC;有 HotSpot 等实现 |
| JRE | 只跑程序不写代码的环境 | 现代 JDK 已包含运行能力,单独装 JRE 已过时 |
| JDK | 开发工具箱 = 编译器 + 标准库 + JVM | javac、java、jar 都在 JDK 的 bin 目录里 |
记忆口诀:JDK 包着 JRE,JRE 包着 JVM。写代码必须装 JDK。
跟着做
步骤 1:确认 JDK 版本
打开终端(Windows 用 PowerShell):
java -version
javac -version
期望输出类似(两者主版本一致):
openjdk version "17.0.10" 2025-01-21
javac 17.0.10
判定规则:
- 两条都有且 ≥ 17:直接往下走,本课程全程用 JDK 17+ 语法
- 只有
java没有javac:装的是运行环境,去装 JDK(推荐 Eclipse Temurin 17 或 21) - 报「不是内部或外部命令」:PATH 没配好,把 JDK 的
bin目录加进环境变量 PATH 后重开终端
步骤 2:跑通第一个程序
新建文件夹 java-lab,在里面新建文本文件 Hello.java(注意:Windows 要显示文件扩展名,防止存成 Hello.java.txt),输入:
public class Hello {
public static void main(String[] args) {
System.out.println("Hello, CodeRoadMap!");
}
}
在 java-lab 目录打开终端,运行:
java Hello.java
期望输出:
Hello, CodeRoadMap!
java Hello.java 是 JDK 11+ 的单文件直跑:内部先编译再立刻运行,适合学习阶段。生产项目不用这个方式,而是走 Maven(第 13 课)。
步骤 3:手动体验「编译 → 运行」两步
javac Hello.java # 生成 Hello.class 字节码
java Hello # 注意:这里不带 .class 后缀,JVM 启动后加载执行
这一步的意义:亲眼看到 .class 文件。它就是你将来部署到 Linux 服务器上的东西——本机 Windows 上编译的 Hello.class,拷到装了兼容 JDK 的 Linux 服务器上,一般直接能跑,这就是「一次编译,到处运行」。
步骤 4:看一眼字节码长什么样(可选但强烈建议)
javap -c Hello.class
会输出一串 aload_0、invokevirtual 之类的指令——这就是 JVM 真正执行的「剧本」。不用看懂,知道它的存在即可:你写的语法会被翻译成这套指令,面试里说的「字节码」就是它。
讲清楚要点
- Java 是先编译后执行的语言:
.java人写,.class机器(JVM)读。编译报错在运行前就被拦下,这是 Java 比 Python/JS 更适合大型工程的原因之一。 - JVM 负责「翻译 + 管理」:翻译指把字节码变成 CPU 能懂的指令(解释执行,热点代码走 JIT 即时编译提速);管理指自动内存分配与垃圾回收(GC),你不用像 C/C++ 那样手动 free。
- 跨平台的是字节码,不是 Java 源码:每个操作系统有自己的 JVM 实现,源码一份,字节码通用,JVM 各自适配。
- JDK 17 是 LTS(长期支持)版本:本站后端和 Spring Boot 3.x 都要求 JDK 17+。学习请直接用 17 或 21,不要用 JDK 8 起步——本课程会用
record、switch 箭头语法、文本块等新特性。 - Java 生态 = 语言 + JVM + 库:Spring Boot、MySQL 驱动、Redis 客户端都是构建在标准库之上的第三方库,语言基础不牢,框架阶段会处处卡壳。
你可能会懵的地方
-
JVM 是用 Java 写的吗? 不是。主流实现 HotSpot 是 C++ 写的本机程序。用 Java 写的叫「元循环 JVM」(如 Jikes RVM),属于学术实现。
-
装了 JDK 21 的机器能跑 JDK 17 编译出的字节码吗? 能。字节码向后兼容:高版本 JVM 能跑低版本编译产物,反过来不行(JVM 17 跑不了 21 编译且开了新特性开关的字节码)。
-
既然 JVM 管 GC,Java 就不会内存溢出吗? 会。GC 只回收「不可达」的对象,集合一直往里塞不清理、连接不关闭,堆照样被打爆,抛
OutOfMemoryError。框架阶段排查的很多线上问题就是这个。 -
为什么本站不用 Python/Node 写后端? Spring Boot 生态成熟、强类型利于多人协作、JVM 高并发性能稳定、Java 后端岗位量大。语言没有银弹,但 Java + Spring 是国内企业后端的事实标准。
-
JIT 是什么,和解释执行什么关系? JVM 先解释执行字节码(快启动),对反复执行的「热点代码」即时编译成本机机器码缓存起来(快运行)。所以 Java 程序「越跑越快」,压测时要预热就是这个道理。
错法对照
| 错法 | 问题 | 正解 |
|---|---|---|
只装了 JRE 或只配了 java 没配 javac | 没法编译,学不了 | 安装完整 JDK 并把 bin 加入 PATH |
文件存成 Hello.java.txt | 编译器找不到类 | 文件资源管理器打开「显示文件扩展名」 |
java Hello.class | 会报「找不到或无法加载主类」 | java Hello,启动命令不带后缀 |
类名 hello 文件名 Hello.java | 编译报错:类名与文件名不一致 | public 类名必须与文件名完全一致(含大小写) |
| 用 JDK 8 学本课程 | record、箭头 switch、文本块全部编译失败 | 安装 JDK 17 或 21 |
卡点急救
javac不是内部或外部命令:确认 JDK 安装目录下bin\javac.exe存在;把该bin目录加入系统环境变量 PATH;重开终端(改 PATH 后旧终端不生效)。java Hello.java报错「找不到文件」:终端当前目录不对。用cd进入Hello.java所在目录,或输入完整路径。- 中文输出乱码:Windows 终端默认编码 GBK。运行前执行
chcp 65001切换 UTF-8,或编译时加-encoding UTF-8。 - 报错
UnsupportedClassVersionError:运行用的 JVM 版本低于编译用的 JDK 版本,统一升级到同一个 JDK。
面试常问
-
JDK、JRE、JVM 的区别? JVM 执行字节码;JRE = JVM + 核心类库,够运行;JDK = JRE + 编译器与开发工具,够开发。包含关系:JDK ⊃ JRE ⊃ JVM。
-
Java 为什么能跨平台? 编译产物是平台无关的字节码,各平台有对应的 JVM 实现负责加载执行。代价是多了一层虚拟机,换来「一次编译,到处运行」。
-
JVM 如何执行字节码? 先解释执行;JIT 编译器把热点代码编译成本机指令缓存,后续直接执行机器码。兼顾启动速度与峰值性能。
-
说说 JVM 的内存区域(高频) 线程共享:堆(对象实例)、方法区/元空间(类信息);线程私有:虚拟机栈(方法调用栈帧)、本地方法栈、程序计数器。入门阶段记住「对象在堆、局部变量在栈」即可。
自测三问
.java到真正执行,中间经过了哪几步?每步的工具/角色是什么?- 为什么说「JDK 包着 JRE 包着 JVM」?写代码用哪个,部署最少需要哪个?
java Hello和java Hello.java分别发生了什么?生产部署走哪种?
小结一句话
Java = 语言 + 字节码 + JVM:源码编译成字节码,JVM 负责翻译执行和内存管理,跨平台与 GC 都来自这一层;开发装 JDK 17+,本站后端 Spring Boot 正跑在这套体系上。
延伸
- Oracle:Java 平台概览
- Eclipse Temurin JDK 下载
- 下一课:基本语法与
main——逐词拆解public static void main(String[] args),搞懂 Java 文件的最小结构。