JVM系列第3讲:到底什么是虚拟机?

我们都知道在 Windows 系统上一个软件包装包是 exe 后缀的,而这个软件包在苹果的 Mac OSX 系统上是无法安装的。类似地,Mac OSX 系统上软件安装包则是 dmg 后缀,同样无法在 Windows 系统上安装。

为什么不同系统上的软件无法安装,这是因为操作系统底层的实现是不一样的。对于 Windows 系统来说,exe 后缀的软件代码最终编译成 Windows 系统能识别的机器码。而 Mac OSX 系统来说,dmg 后缀的软件代码最终编译成 Mac OSX 系统能识别的代码。

系统软件无法通用是一个常见的问题。但使用过 Java 的同学都知道,Java 代码可以在服务端(Linux 系统)运行,也可以在 Windows 系统运行,但我们并没有生成多份不同的代码。所以 Java 语言是如何做到的呢?

与其他语言不同,Java 语言并不直接将代码编译成与系统有关的机器码,而是编译成一种特定的语言规范,这种语言规范我们称之为字节码。无论 Java 程序要在 Windows 系统,还是 Mac OSX 系统,抑或是 Linux 系统,它首先都得编译成字节码文件,之后才能运行。

但即使编译成字节码文件了,各个系统还是无法明白字节码文件的内容,这时候就需要 Java 虚拟机的帮助了。Java 虚拟机会解析字节码文件的内容,并将其翻译为各操作系统能理解的机器码。

简单地说,对于同样一份 Java 源码文件,我们编译成字节码之后,无论是 Linux 系统还是 Windows 系统都不认识。这时候 Java 虚拟机就是一个翻译官,在 Linux 系统上翻译成 Linux 机器码给 Linux 系统听,在 Windows 系统上翻译成 Windows 机器码给 Windows 系统听。这样一来,Java 就实现了「Write Once,Run Anywhere」的伟大愿景了。

在 Java 虚拟机还没出现之前,为了支持软件在不同系统上运行,我们必须在多个平台写多份代码,分别对应特定的系统。但 Java 虚拟机出现之后,你只需要按照特定规范编译书写,编译器编译成字节码文件后,虚拟机会帮你将字节码生成对应的 Windows Code 和 Mac Code。本质上最终还是会生成 Windows Code 和 Mac Code 两份机器代码,但对于开发人员来说,却只需要写一次代码了。Java 虚拟机帮开发人员承担了重复的工作,让开发效率更高了。

很多初学者关于 Java 虚拟机有一个误区,他们会觉得 Java 虚拟机只能运行 Java 代码。但实际上 Java 虚拟机运行的是字节码文件。换句话说,如果你用 php 语言写一段代码,并自己用特定编译器能生成符合字节码规范的字节码文件,那么 Java 虚拟机也是可以运行的。

所以虽然名字是 Java 虚拟机,但 Java 虚拟机与 Java 语言没有直接关系,它只按照 Java 虚拟机规范去读取 Class 文件,并按照规定去解析、执行字节码指令,仅此而已。

如果你够牛逼,你完全可以写一个编译器,将 PHP 语言代码编译成符合 Java 虚拟机规范的字节码文件,那么 Java 虚拟机也是可以执行的。

准确地说,Java 虚拟机与字节码文件(Class文件)绑定。

最后,让我们回顾一下,到底什么是虚拟机?其实 Java 虚拟机就是一个字节码翻译器,它将字节码文件翻译成各个系统对应的机器码,确保字节码文件能在各个系统正确运行。

参考资料

JVM系列目录


如果只是看,其实无法真正学会知识的。为了帮助大家更好地学习,我建了一个虚拟机群,专门讨论学习 Java 虚拟机方面的内容,每周针对我所发文章进行讨论答疑。如果你有兴趣,关注「Java技术精选」公众号,通过右下角菜单「入群交流」加我好友,小助手会拉你入群。