7.1 虚拟机基本概念

“编写一次,到处运行”是Java语言吸引开发人员的重要原因之一。用Java语言编写的程序,可以在任何平台上运行,只需要在操作系统之上安装Java运行环境即可。某些编程语言的开发平台中并没有虚拟机的概念,而是通过直接从源代码生成目标操作系统上的二进制文件来运行。不同操作系统上的二进制文件是无法兼容的。以C/C++语言为例,在Windows平台上编译C/C++源代码所生成的可执行文件,无法在Linux平台上运行。当需要使用程序的时候,用户要么直接下载其操作系统对应的可执行文件,要么根据源代码自行编译和链接来得到可执行文件。对程序的开发人员来说,如果程序需要支持不同的操作系统平台,则需要做很多工作来确保程序在不同的操作系统平台上都可以正常工作,其中包括对程序进行修改以适应不同的操作系统平台。虽然有一些类库可以帮助解决这个问题,但是开发人员的任务量仍然比较大。

Java平台早在开发时就引入了虚拟机的概念。Java程序不是由操作系统以可执行文件的形式直接运行的,而是运行在Java虚拟机中的。在运行Java程序的时候,需要指定一个主Java类。Java虚拟机在启动之后,会从主Java类的main方法开始执行。当main方法执行结束之后,Java虚拟机会自动终止。每个Java虚拟机在运行时是底层操作系统上的一个独立的进程。比如,当在Windows操作系统上运行Java程序的时候,可以从任务管理器的进程列表中看到名为“java.exe”或“javaw.exe”的进程,这些就是Java虚拟机的进程。

虚拟机的作用主要有两个:一个是为应用程序屏蔽底层操作系统的细节,另外一个则是为应用程序提供必要的运行时的支持能力。不同的操作系统在实现上存在很多差异。跨平台的应用程序需要自己来考虑这些不同,并在代码中进行处理。这通常意味着更长的开发时间和更高的维护成本,也意味着需要更多熟悉不同平台的开发人员。很多程序都采用多线程的方式来提高性能。在创建线程时,Windows平台上的API与Linux上的相关API就存在很大不同,在程序中需要通过不同的分支代码来进行处理。虚拟机的作用就在于处理这些细节,为程序提供统一的接口。同样的线程操作,在Java语言中可以通过抽象的java.lang.Thread类来完成。而Thread类在不同平台上实现的不同,则由虚拟机来负责处理。除此之外,虚拟机为在其上运行的应用程序提供了必要的支持。以Java虚拟机为例,这些支持包括基本类型和操作符、对象模型、Unicode支持、动态链接、垃圾回收器、内存模型和访问控制等。虚拟机所提供的这些功能,是Java程序运行时的基础。在Java语言中可以与这些功能进行交互,比如,第4章中介绍的Java语言中的Unicode相关的内容。其他的相关内容也会在之后的章节中进行介绍。简而言之,虚拟机的作用相当于一个简化后的操作系统,它所提供的功能不仅丰富,而且规范、统一。

随着Java语言的流行,在编程语言开发平台中使用虚拟机也成了一种被广泛认可的做法。微软的.NET框架也采用了类似的架构。.NET架构中的虚拟机被称为通用语言运行环境(Common Language Runtime, CLR)。.NET平台支持的各种编程语言的代码,如C#和VB.NET,会先被编译成CLR上的中间语言(Common Intermediate Language, CIL)的形式,类似于Java中的字节代码。CIL再由CLR来运行。这种使用模式与Java的做法是非常类似的。