JVM规范第 1章:从一段历史到「JVM 并不认识 Java」

本教程基于 Oracle 官方《The Java Virtual Machine Specification》(Java SE 26)第 1 章《Introduction》整理编写。它是一份「读规范前先读」的导读------帮你搞清楚 JVM 是什么、为什么存在、规范这本书到底在讲什么、以及怎么正确地读这本「天书」。

你将学到

  • Java 和 JVM 是怎么诞生的,为什么会有「一次编写,到处运行」
  • 一个反直觉的关键事实:JVM 根本不认识 Java 这门语言
  • class 文件版本号(major.minor)是什么,以及 Java SE 26 对应的版本号
  • 整本 JVM 规范的章节地图,以及哪些内容「搬家」去了《Java 语言规范》
  • 规范的「记号约定(Notation)」------怎么看懂它那些字体和 §x.y 引用
  • 什么是「预览特性(Preview Features)」,以及它为什么被锁死在某个版本

前置知识

  • 写过 Java,知道 .java 文件要编译成 .class 才能跑
  • 听过「JVM 是 Java 的虚拟机」这种说法(本篇会纠正它的不严谨之处)
  • 不需要任何 JVM 内部知识,这一章本来就是给「零基础读规范」的人准备的

一、历史:JVM 是为了「网上的安全小程序」而生的

很多人以为 Java 一开始就是给后端/企业级用的,其实不是。

Java 是一门通用、并发、面向对象 的语言,语法像 C/C++,但砍掉了那些让 C/C++ 复杂、易错、不安全的特性。它最初是为了联网的消费类设备(networked consumer devices) 而设计的------目标是在不同硬件架构上安全地分发软件组件。

真正让它爆红的是 万维网(WWW)

  • 浏览器让普通人能轻松看多媒体内容,但 HTML 太「静态」、表达力有限
  • HotJava 浏览器第一次展示了「把程序嵌进 HTML 页面」的能力:程序跟着 HTML 一起下载,下载前会被严格检查是否安全,然后才运行
  • 这些编译后的程序和 HTML 一样,与网络、主机无关------不管从哪来、跑在什么机器上,行为一致

于是有了那句著名的口号:Write Once, Run Anywhere(一次编写,到处运行)

一句话:JVM 的初心是「让一段二进制代码能安全地跨网络、跨机器运行」。这个初心,决定了它后面所有的设计。


二、JVM 是什么:一台「抽象的计算机器」

规范里对 JVM 的定位非常精准:

The Java Virtual Machine is the cornerstone of the Java platform.(Java 平台的基石)

它负责三件事:

  1. 硬件与操作系统无关性(你编译一次,到处能跑)
  2. 编译后代码体积小
  3. 保护用户免受恶意程序侵害

再看更本质的一句:

The Java Virtual Machine is an abstract computing machine.(JVM 是一台抽象的计算机器)

它和真实机器一样,有指令集 ,并在运行时操作各种内存区域 。用虚拟机来实现一门语言并不稀奇------最有名的先驱是 UCSD Pascal 的 P-Code 机器

2.1 关键事实:JVM 不认识 Java

这是整章最重要的一句话,请记住:

The Java Virtual Machine knows nothing of the Java programming language, only of a particular binary format, the class file format.

JVM 只认一种二进制格式------class 文件。一个 class 文件里包含:

  • JVM 指令(也就是字节码 bytecode
  • 一个符号表(symbol table)
  • 其他辅助信息

这带来一个威力巨大的推论:

任何能用合法 class 文件表达功能的语言,都能跑在 JVM 上。

所以今天你能在 JVM 上跑 Kotlin、Scala、Groovy、Clojure......不是因为它们「像 Java」,而是因为它们都编译成了 class 文件。JVM 是它们的「交付载体(delivery vehicle)」。

纠正一个常见误解:「JVM 是 Java 的虚拟机」这话不严谨。更准确的说法是:JVM 是 class 文件的执行引擎,Java 只是它的第一个、也是最著名的宿主语言。

2.2 JVM 不绑定任何实现技术

另一点容易被忽略:JVM 不假定任何特定的实现技术、主机硬件或操作系统。

  • 第一个原型是 Sun 公司在一台手持 PDA 类设备上用软件模拟出来的
  • Oracle 现在的实现能在手机、桌面、服务器上运行
  • 本质上不是解释器 ------既可以被解释,也可以把指令集直接编译成硅片 CPU 的指令(这就是 JIT / AOT)
  • 甚至可以用微码(microcode)或直接用硬件电路实现

这就是为什么同一个 .class 在不同 JVM 上「行为一样、性能不同」------行为由规范管,性能由实现管。


三、class 文件版本号:它锁定了你能跑在多新的 JVM 上

class 文件是带版本号 的,格式为 major.minor(主版本.次版本),表示这个文件依赖哪个 Java SE 发布版,并影响 JVM 如何解读它。

本版规范(Java SE 26)的 JVM:

  • 兼容《Java 语言规范 Java SE 26 版》
  • 支持 class 文件 major 版本号 45 ~ 70(含)
  • 工具通常会采用最新的 major 版本号来用上新特性;但旧版本号的文件一般也能在未来的 JVM 上继续跑

下面这张表是官方给出的「Java SE 发布版 ↔ class 文件主版本号」对照(节选自规范 Table 1.2-A):

Java SE 发布 发布时间 支持的最早主版本 支持的最新主版本
1.0.2 1996-05 45 45
1.1 1997-02 45 45
1.2 1998-12 45 46
1.4 2002-02 45 48
5.0 2004-09 45 49
6 2006-12 45 50
7 2011-07 45 51
8 2014-03 45 52
11 2018-09 45 55
17 2021-09 45 61
21 2023-09 45 65
22 2024-03 45 66
23 2024-09 45 67
24 2025-03 45 68
25 2025-09 45 69
26 2026-03 45 70

记一个实用数字:Java SE 26 → class 文件 major 70 。你用 javap -v 看到的 major version: 70 就对应 JDK 26 编译出来的类。


四、规范的章节地图:这本书到底讲什么

第 1 章还把整本书的骨架画了出来,读之前先有个地图:

章节 内容
第 2 章 JVM 架构总览(数据类型、运行时数据区、栈帧、指令集...)
第 3 章 把 Java 语言代码编译成 JVM 指令集
第 4 章 class 文件格式(与平台无关的二进制格式)
第 5 章 JVM 的启动,以及类/接口的加载、链接、初始化
第 6 章 指令集,按操作码助记符的字母顺序排列
第 7 章 操作码助记符按操作码数值索引的对照表

4.1 哪些内容「搬走了」

有个重要变化值得注意:早期版本(第二版)里,规范自己附带了「Java 语言概览」和「线程与锁的内存模型」两章;在 Java SE 26 版里,这两块被移到了《Java 语言规范》(JLS)

  • Java 语言本身 → 看 The Java Language Specification, Java SE 26 Edition
  • 线程与锁 → 看 JLS 第 17 章(源自 JSR 133 专家组制定的《Java 内存模型与线程规范》)

所以现在的 JVM 规范更「纯粹」:它只讲「class 文件 + 指令集 + 运行时语义」,语言层面的事交给 JLS。读的时候别找错书。


五、怎么读这本规范:记号约定(Notation)

规范有大量固定的「排版暗语」,提前看懂能省很多事:

  1. 单个标识符 N → 默认指 java.lang 包下的类/接口(如写 String 就是 java.lang.String);其它包必须用全限定名。
  2. java.* 及其子包下的类 → 默认指「由**引导类加载器(bootstrap class loader)**加载」的那个。
  3. 交叉引用 :规范内部用 (§x.y);引用 JLS 时用 (JLS §x.y)
  4. 字体含义
    • 等宽字体:JVM 数据类型、异常、错误、class 文件结构、Prolog 代码、Java 代码片段
    • 斜体:JVM「汇编语言」(操作码 opcode 和操作数)、运行时数据区的条目、新术语、强调
  5. 非规范性文本(non-normative) :用小号、缩进的文字呈现,用来给「直觉、理由、建议、例子」做补充说明------它不是强制规定,但能帮你理解。

读规范时养成习惯:看到小号缩进文字,知道那是「解释」,不是「规定」;看到 §4.1 这种,直接跳过去对照。


六、预览特性(Preview Features):为什么一个新语法会被「锁死」在某个版本

「预览特性」是 Java 近年迭代的重要机制,第 1 章专门讲它:

一个预览特性可以是:

  • 一门语言的新特性(preview language feature)
  • JVM 的一个新特性(preview VM feature)
  • java.* / javax.* 命名空间里新增的模块/包/类/接口/字段/方法等(preview API)

它的特点是:完整定义、完整实现,但「临时」 。发布出来是为了收集真实使用的开发者反馈,可能将来变成永久特性,也可能被改掉或移除。

6.1 限制:默认关闭,且不能只开一部分

  • 编译期和运行期都默认禁用预览特性,必须由用户显式开启
  • 实现不允许「只开启其中某几个」预览特性------要么全开,要么全关

6.2 一个容易踩坑的细节:预览 class 文件被绑死在版本上

一个 class 文件「依赖 Java SE N(N≥12)的预览特性」,当且仅当:

  • 它的 major 版本号 = Java SE N 支持的最新主版本号
  • 它的 minor 版本号 = 65535

举例:版本号 66.65535 依赖 Java SE 22 的预览特性(因为 66 是 Java SE 22 支持的最新主版本)。

关键后果 :这类 class 文件被绑死在那个发布版上 ,即使你开启了预览特性,也不能在别的发布版 JVM 上加载------因为不同发布版的预览特性内容可能不同甚至缺失。

这解释了为什么你有时用 JDK 22 开了 --enable-preview 编译出的类,拿到 JDK 23 上跑会直接失败。它不是 bug,是规范刻意设计的隔离。

6.3 当前状态

规范明确写到:Java SE 26 没有定义任何预览 VM 特性(preview language feature / API 另算,由对应文档说明)。

相关推荐
TechExplorer3651 小时前
Tomcat 下载与安装
java·tomcat
程序员贺加贝1 小时前
列表导出不够用-SaaS-ERP-单据详情导出的-Provider-模板与文档型-Excel-设计
java·后端·设计模式·架构·excel
SimonKing1 小时前
写文档的最佳搭档:Typora+PicList+SM.MS
java·后端·程序员
侧耳倾听1111 小时前
disruptor 从入门到使用
java
龙智DevSecOps解决方案1 小时前
WildFly vs JBoss vs GlassFish:2026年Java应用服务器选型对比与Perforce JRebel加速实践
java·应用服务器·jrebel·wildfly
孫治AllenSun1 小时前
【LangChain4J-04】Tool 工具的使用
java·人工智能
南城以南溫暖如初1471 小时前
树洞交友系统架构设计与匿名聊天实战指南
java·spring boot·mysql·系统架构·vue·mybatis·交友
lemon_sjdk1 小时前
JavaFX 响应式核心:从属性绑定、失效通知到生命周期管理
java
QCodingDev2 小时前
Spring AI Alibaba Graph实战:从ReAct Agent到Workflow,企业AI复杂流程该如何编排?
java·人工智能·spring·ai·ai编程·企业ai