Java | 为什么 Java 实现了平台无关性?

前言

  • 从最初学习Java开始,我们就知道Java的口号是:“一次编写,到处运行”。没有了平台的束缚,使得我们再编写Java时并不需要(那么)关心将来运行程序的平台。
  • 那么,Java是如何实现 平台无关性的呢?今天我们来讨论这个问题。
# 咬文嚼字 #

为什么是“不需要(那么)关心”,而不是“不需要关心”?因为在工程实践中,不全面考量运行程序的系统 / 网络 / 硬件 / 国家等因素是不可能的。

目录

1. 运行环境 = 操作系统 + 硬件

首先,理解清楚什么是平台?平台是指程序的运行平台,或者称为运行环境,具体来说:运行环境 = 操作系统 + 硬件(主要是CPU)

1.1 操作系统屏蔽了除 CPU 外的硬件差异

操作系统(Operating System)是管理计算机硬件与软件资源的程序。对于现代应用程序来说,它们是不会直接操作硬件的,而是采用向操作系统发送指令的方式来间接控制硬件,这些指令就是系统调用

系统调用是操作系统与应用程序之间的接口(Application Programming Interface,API)。然而不同操作系统提供的 API 是不同的,这样的话,程序调用 API 的代码也会因操作系统不同而不同,因此操作系统是运行环境的要素之一。

应用通过系统调用间接控制硬件

1.2 CPU 只能运行本地代码

每种CPU只能“读懂”自身支持的机器语言或者本地代码(native code),而每种CPU使用的指令集不尽相同。因此,任何高级编程语言 / 汇编语言编写的程序,最后都需要“翻译”为CPU能够读懂的本地代码。

本地代码是 CPU 唯一的语言

下面,我们对比C/C++ & Java两种语言是使用什么方式将源代码转换为本地代码的。


2. C/C++ 如何将源代码转换为本地代码

  • 步骤1:编译生成目标文件(编译时)
  • 步骤2:链接生成可执行文件(编译时 or 运行时)

3. Java 如何将源代码转换为本地代码

  • 步骤1:编译前端生成 Class文件(编译时)
  • 步骤2:编译后端解释或编译为本地代码(编译时 or 运行时)

关于 Java 编译过程 的更多介绍,请阅读文章:《Java | 聊一聊编译过程(编译前端 & 编译后端)》


4. Java 虚拟机的公有协议与私有实现

  • Java 虚拟机的协议 指的是《Java 虚拟机规范》,它规定了 Java 虚拟机的概念模型;
  • Java 虚拟机实现 是指各种平台上具体的虚拟机实现,例如 Classic VMHotSpot VM

在这个概念模型下,不同的虚拟机实现有统一的输入输出模型:

所有虚拟机实现的输入与输出都是一致的:输入为Class 文件,处理过程是字节码解释执行的等效过程,最终输出的是预期的执行结果。这样的方式即保证了不同平台不同实现的虚拟机行为一致,也提高了伸缩性。不同平台的虚拟机实现可以根据具体平台特点,赋予虚拟机实现更多的特点:更高的性能 or 更低的内存消耗 。

关于 Class 文件 的更多介绍,请阅读文章:《Java | 请概述一下 Class 文件的结构》


5. 总结

虚拟机与字节码是Java实现无关性的基础。首先,与不同于C/C++Java将程序存储格式从本地代码转变为字节码;其次,不同平台的虚拟机都统一采样字节码作为输入语言,并统一遵守《Java 虚拟机规范》,最终提供了一个不依赖于特定操作系统 & 硬件的运行环境,即平台无关性。

虚拟机提供了统一的运行环境

参考资料

  • 《程序是怎样跑起来的》 (第7、8章)—— 矢泽久雄
  • 《深入理解Java虚拟机(第3版本)》(第6、7、8章)—— 周志明
  • 《深入理解Android:Java虚拟机ART》(第2章) —— 邓凡平

推荐阅读

感谢喜欢!你的点赞是对我最大的鼓励!欢迎关注彭旭锐的简书!