点赞关注,不再迷路,你的支持对我意义重大!
🔥 Hi,我是丑丑。本文 「Java 路线」| 导读 —— 他山之石,可以攻玉 已收录,这里有 Android 进阶成长路线笔记 & 博客,欢迎跟着彭丑丑一起成长。(联系方式在 GitHub)
前言
- 从最初学习
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
能够读懂的本地代码。
下面,我们对比C/C++ & Java
两种语言是使用什么方式将源代码转换为本地代码的。
2. C/C++ 如何将源代码转换为本地代码
- 步骤1:编译生成目标文件(编译时)
- 步骤2:链接生成可执行文件(编译时 or 运行时)
3. Java 如何将源代码转换为本地代码
- 步骤1:编译前端生成 Class文件(编译时)
- 步骤2:编译后端解释或编译为本地代码(编译时 or 运行时)
关于 Java 编译过程 的更多介绍,请阅读文章:《Java | 聊一聊编译过程(编译前端 & 编译后端)》
4. Java 虚拟机的公有协议与私有实现
- Java 虚拟机的协议 指的是《Java 虚拟机规范》,它规定了 Java 虚拟机的概念模型;
-
Java 虚拟机实现 是指各种平台上具体的虚拟机实现,例如
Classic VM
、HotSpot VM
;
在这个概念模型下,不同的虚拟机实现有统一的输入输出模型:
所有虚拟机实现的输入与输出都是一致的:输入为Class 文件
,处理过程是字节码解释执行的等效过程,最终输出的是预期的执行结果。这样的方式即保证了不同平台不同实现的虚拟机行为一致,也提高了伸缩性。不同平台的虚拟机实现可以根据具体平台特点,赋予虚拟机实现更多的特点:更高的性能 or 更低的内存消耗 。
关于 Class 文件 的更多介绍,请阅读文章:《Java | 请概述一下 Class 文件的结构》
5. 总结
虚拟机与字节码是Java
实现无关性的基础。首先,与不同于C/C++
,Java
将程序存储格式从本地代码转变为字节码;其次,不同平台的虚拟机都统一采样字节码作为输入语言,并统一遵守《Java 虚拟机规范》,最终提供了一个不依赖于特定操作系统 & 硬件的运行环境,即平台无关性。
参考资料
- 《程序是怎样跑起来的》 (第7、8章)—— 矢泽久雄
- 《深入理解Java虚拟机(第3版本)》(第6、7、8章)—— 周志明
- 《深入理解Android:Java虚拟机ART》(第2章) —— 邓凡平
创作不易,你的「三连」是丑丑最大的动力,我们下次见!