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

4. 【Java】JVM 的秘密:Java 为什么能“一次编写,到处运行“

摘要:本文深入解析 Java 虚拟机(JVM)的核心原理,揭秘 Java "一次编写,到处运行"的跨平台奥秘。从编译与运行分离、JVM/JRE/JDK 三者的关系,到 JVM 内部构造(类加载器、运行时数据区、执行引擎、垃圾回收)以及完整的程序执行流程,通过生动的比喻和清晰的图示,帮助 Java 初学者和开发者构建对 Java 运行时的系统性认知。

关键词:Java 虚拟机 (JVM), 字节码, 跨平台, 垃圾回收 (GC), Java 运行时环境 (JRE)


前几篇文章,我们从认识 Java 开始,搭好了开发环境,还亲手写出了第一个Hello, World!程序。当时我说,Java 最大的魅力之一就是"一次编写,到处运行"——你在 Windows 上写的代码,拿到 Linux 或 macOS 上照样能跑,不需要任何修改。

但你有没有想过:这到底是怎么做到的?为什么 C 语言写的程序不行,Java 就可以?

今天我们就深入底层,揭开 JVM(Java 虚拟机)的神秘面纱。放心,我不会讲太多晦涩的理论,而是用你能听懂的比喻,把这件事讲透。


1. 从 Hello World 说起 —— 编译和运行是两个步骤

还记得上一篇我们写的HelloWorld.java吗?我们在 IDEA 里点了一下绿色的"运行"按钮,程序就跑了。但 IDEA 在背后偷偷做了两件事:

  1. 编译:把HelloWorld.java(我们看得懂的源代码)转换成一种叫做字节码(Bytecode)的文件HelloWorld.class
  2. 运行:启动 JVM,加载HelloWorld.class,然后执行里面的指令。

这两个步骤是独立的。你可以手动在命令行里体验一下:

# 第一步:编译javac HelloWorld.java# 第二步:运行javaHelloWorld

编译后,你会看到一个HelloWorld.class文件——它就是 Java 字节码。这个文件不是机器码,计算机的 CPU 不能直接执行它。它需要被 JVM 解释或编译成当前平台能识别的机器码才能运行。

💡 打个比方:你写了一篇中文演讲稿(源代码),有人把它翻译成了国际通用语(字节码),然后到了美国,当地翻译把它转成英文讲给美国人听;到了日本,转成日文讲给日本人听。无论去哪个国家,那份国际通用语版本都是同一份——这就是 Java 字节码。


2. JVM、JRE、JDK —— 从内部视角再看一遍

第二篇我们简单对比过三者的关系,今天从 JVM 内部视角再看一遍,理解会更深。

名称全称包含内容作用
JVMJava Virtual Machine类加载器、运行时数据区、执行引擎、GC运行字节码
JREJava Runtime EnvironmentJVM + 核心类库(如SystemString等)运行 Java 程序(不能开发)
JDKJava Development KitJRE + 开发工具(javacjarjdb等)开发并运行 Java 程序

简单地说:

  • JVM是"引擎",是运行的核心。
  • JRE是"引擎 + 轮胎 + 方向盘",有了它车能跑,但你不能造车。
  • JDK是"整车 + 工厂 + 修车工具",你不仅能开,还能造车、修车。

JVM、JRE、JDK 的关系:
这三个缩写是 Java 世界里最基础的概念,画个图就清楚了:

我们在第一篇文章里装的是 JDK 21,所以它包含了 JRE 和 JVM。当你运行java命令时,实际上是在启动 JVM。


3. 跨平台的秘密 —— 字节码 + JVM

现在我们可以回答那个核心问题了:为什么 Java 能跨平台?

答案就是两个关键设计:

  1. Java 源代码编译成字节码,而不是直接编译成特定平台的机器码。
  2. 每个平台都有自己的 JVM 实现——Windows 有 Windows 版 JVM,Linux 有 Linux 版 JVM,macOS 有 macOS 版 JVM。

你写的代码只需要编译成一份字节码,然后用哪个平台的 JVM,它就会自动把字节码转换成对应平台能执行的机器码。

再次打个比方:你写了一份国际通用语的文件(字节码),然后你把它带到美国,美国翻译官(JVM for Windows)把它读给美国人听;带到日本,日本翻译官(JVM for macOS)读给日本人听。你只需要带一份文件,翻译官们各显神通。

这就是“一次编写,到处运行”的本质。


4. JVM 内部构造 —— 它到底长什么样?

为了让你更直观地理解 JVM 是怎么工作的,我把它的核心组成部分画成一个简单的模型。这里不要求你完全记住,有个印象就好:

+------------------------------------------+ | JVM 架构简图 | +------------------------------------------+ | ① 类加载器(Class Loader) | | 把 .class 文件加载到内存中 | +------------------------------------------+ | ② 运行时数据区(Runtime Data Area) | | ┌─────────┬─────────┬──────────┐ | | │ 堆 │ 栈 │ 方法区 │ | | │ (对象) │ (局部变量)│ (类信息) │ | | └─────────┴─────────┴──────────┘ | | (实际上还包括程序计数器、本地方法栈等) | +------------------------------------------+ | ③ 执行引擎(Execution Engine) | | 把字节码翻译成机器码并执行 | | (解释器 + JIT 编译器) | +------------------------------------------+ | ④ 垃圾回收(Garbage Collector) | | 自动清理不再使用的对象 | +------------------------------------------+
  • ① 类加载器(Class Loader)

它的工作很简单:找到.class文件,读取它里面的字节码,然后把它加载到内存中。我们写程序时用到的StringSystem这些类,也是由类加载器从 JDK 的核心库中加载进来的。

  • ② 运行时数据区(Runtime Data Area)

这里是程序运行时的"工作空间",主要包含几块:

  • 堆(Heap):存放所有通过new创建的对象。它是所有线程共享的,也是垃圾回收的主要战场。
  • 栈(Stack):每个线程都有自己的栈,用来存放局部变量和方法调用的信息。方法执行时压栈,执行完出栈。
  • 方法区(Method Area):存放类的结构信息(如类名、方法定义、静态变量等)。在 JDK 8 之前它在 JVM 堆中,JDK 8 之后移至元空间(Metaspace),使用本地内存管理。
  • 程序计数器、本地方法栈等:其他辅助区域,初学阶段不必深究。

初学者不需要深究每个区域的细节,只要知道 JVM 为你的程序划分了不同的"仓库"来存放不同的东西就行。

  • ③ 执行引擎(Execution Engine)

这是 JVM 的"大脑"。它把字节码(一种抽象的指令集)转换成当前 CPU 能理解的机器码。早期的 JVM 采用解释执行(一条一条地解释,速度较慢),现在的 JVM 引入了JIT(即时编译)技术——它会识别出频繁执行的热点代码,直接编译成机器码并缓存起来,后续直接运行机器码,速度大幅提升。

  • ④ 垃圾回收(Garbage Collector,GC)

这是我们之前提到的"自动内存管理"的核心。GC 会周期性扫描堆内存,找出那些不再被任何引用指向的对象,然后把它们占用的空间回收掉,供后续使用。

想一下:当你写new Student()创建一个学生对象,并把它赋给变量s。当s后来被赋值为null时,那个学生对象就没有人引用了,GC 就会在合适的时机把它清理掉。你不用手动deletefree——Java 替你干了。


5. 垃圾回收 —— 你的"内存清洁工"

GC 可能是 JVM 中最"智能"的部分。它的核心思想是可达性分析:从一组称为"GC Roots"的起点(如当前运行中的线程、静态变量等)出发,沿着引用链标记所有能到达的对象。那些无法被标记到的对象,就是不再使用的"垃圾",会被 GC 回收。

现代 JVM 有多种 GC 算法,例如:

  • G1 GC(JDK 9+ 默认):把堆分成多个区域,优先回收垃圾最多的区域
  • ZGC(JDK 11+ 引入,JDK 21 增强):超低延迟,适合大内存场景
  • 分代式 ZGC(JDK 21):在 ZGC 基础上引入分代思想,进一步提升性能

我们以后会有专门的文章讲 GC 调优,现在你只需要记住:GC 自动帮你管理内存,你基本不需要操心对象的释放——这大大减轻了开发者的负担。


6. 一个完整的运行流程 —— 从 .java 到屏幕输出

现在把整个流程串起来:

你写的源代码:HelloWorld.java ↓ (javac 编译) 字节码文件:HelloWorld.class ↓ (java 命令启动 JVM) JVM 类加载器把 HelloWorld.class 加载到内存 ↓ JVM 执行引擎将字节码翻译成机器码 ↓ CPU 执行机器码,执行 System.out.println(...) ↓ 控制台输出:Hello, World!

每一步都清晰可见,这也是 Java 的设计理念:把底层复杂性封装起来,让开发者专注于逻辑


今天的总结

今天我们聊了三个核心内容:

  1. 编译与运行是分离的——javac产生字节码,java启动 JVM 执行字节码。
  2. JVM、JRE、JDK 的关系——层层包含,JDK 最大,JVM 最小但最核心。
  3. 跨平台的本质——字节码 + 各平台的 JVM 实现,做到"一次编写,到处运行"。
  4. JVM 的核心组件——类加载器、运行时数据区、执行引擎、垃圾回收。
  5. GC 帮你自动管理内存,你不需要手动释放对象。

你现在已经站在了一个更高的视角看待 Java:不只是写代码,而是理解了代码背后运行的"舞台"。这个舞台就是 JVM,它承载了你的程序的一生。


动手试试

  1. 打开命令行,进入你之前HelloWorld.java所在的目录,手动执行javac HelloWorld.javajava HelloWorld,观察生成的.class文件。
  2. 用文本编辑器(如记事本)打开HelloWorld.class,你会看到一堆"乱码",那其实是字节码的二进制表示。虽然看不懂,但你能感受到它和原始代码的区别。
  3. javap -c HelloWorld命令查看字节码指令(如果你装了 JDK),你会看到类似getstaticldcinvokevirtual这样的指令。感受一下 Java 底层的样子。

下篇开始,我们就要正式进入 Java 语法的学习了。第一篇讲的是"代码的骨架"。我们会详细拆解一个 Java 程序的基本结构,包括包、导入、类、方法等。别担心,我会带着你一步步掌握。

我们下一篇见。😃

📌 获取本系列示例代码请访问 GitCode。

http://www.jsqmd.com/news/1176940/

相关文章:

  • python数据可视化技巧的100个练习 -- 8. 使用 Python 可视化多个函数
  • 2026 铜川耀州黄金回收规范化盘点:告别小作坊套路,30 年零差评连锁全域免费上门 - 福金阁黄金回收
  • 分享一套锋哥原创的基于Python的会员管理系统(带微信小程序会员端)(FastAPI+Vue3)优质版
  • 2026 龙州黄金回收实地走访:3 大收割套路深度拆解,三大 30 年零差评老牌全城全覆盖免费上门 - 福金阁黄金回收
  • LinkSwift:八大网盘直链下载助手的完整开发者指南
  • 【信息科学与工程学】【通信工程】第七十七篇 城域网+FTTR/FTTB/FTTC/FTTO的数学分析01
  • NVIDIA多模态嵌入模型架构揭秘:Llama 3.2 1B + SigLip2 400M的完美结合
  • 2026年6月成都装修公司排行榜|权威实测评测(覆盖成都全域) - 推荐官
  • 【计算机工具类-协作工具Skills】cal-com-automation 技能
  • unipp中 @tap 运行到小程序,不生效
  • MiniMax-M2.5-NVFP4推理优化技巧:让你的AMD GPU推理速度提升300%
  • 地球物理大地测量学计算系列之十广义Stokes/Hotine数值积分外部高程异常计算
  • MiniMax-M2.7-NVFP4模型配置详解:理解3072隐藏层与256专家的设计原理
  • ChatDocs完全指南:如何快速搭建本地文档智能问答系统
  • 2026 年长武靠谱的2507不锈钢管平台深度剖析,扔掉304吧!这种双相钢才是化工厂真正的省钱利器 - 行业推荐【认证官】
  • Docker容器化部署:AMD MiniMax-M2.1-MXFP4生产环境最佳实践
  • 内存狂飙到32G导致OOM?我用C# IMemoryOwner手搓“零拷贝”引擎,把国产库驱动的GC压力按在地上摩擦!
  • 宝珀中国官方售后服务中心|服务热线及门店详细地址权威信息声明(2026年7月最新) - 宝珀官方售后服务中心
  • 让AI读懂你的文档:Langchain-Chatchat本地知识库构建实战
  • Redux-cycles vs Redux-thunk:为什么函数式响应式编程是更好的异步解决方案
  • 揭秘 websocket-client 内部架构:核心组件与设计模式解析
  • Fullmoon条件验证与表单处理:构建安全Web应用的完整指南
  • Emacs-wgrep最佳实践:10年经验用户分享的高效工作流程
  • 3. 【Java】Hello, World!:第一行 Java 代码
  • 江诗丹顿中国官方售后服务中心|网点地址与客服电话权威信息声明(2026年7月最新) - 江诗丹顿官方服务中心
  • 多 Agent 协作skills首发
  • AI 写达梦/金仓代码疯狂翻车?我手撸了一套“信创专属 AI 生成引擎”,把大模型的方言幻觉按在地上摩擦!
  • 29-杨逢昌:制造业车间工装器具散乱损耗解决方案——器具三权标准化管控体系,无效找物时间缩减80%
  • Human-Level Reasoning: A Comparative Study of Large Language Models on Logical and Abstract Reaso...
  • 南开大学2021创新实践课程:如何配置GRUB引导LFS系统