第2章 字节码的编译原理
Java 最初诞生的目的就是为了在不依赖于特定的物理硬件和操作系统环境下运行,那么也就是说 Java 程序实现跨平台特性的基石其实就是字节码。 Java 之所以能够解决程序的安全性问题、跨平台移植性等问题,最主要的原因就是 Java 源代码的编译结果并非是本地机器指令,而是字节码。当 Java 源代码成功编译成字节码后,如果想在不同的平台上面运行,则无需再次编译,也就是说 Java 源码只需一次编译就可处处运行,这就是“ Write Once, Run Anywhere”的思想。所以注定了 Java 程序在任何物理硬件和操作系统环境下都能够顺利运行,只要对应的平台装有特定的 Java 运行环境, Java 程序都可以运行,虽然各个平台的 Java 虚拟机内部实现细节不尽相同,但是它们共同执行的字节码内容却是一样的。那么想要让一个 Java 程序正确地运行在 JVM 中, Java 源码就必须要被编译为符合 JVM 规范的字节码。关于规范,开发人员在使用 Java 语言编写一个 Java 程序时需要遵循 Java 语法规范,而将源码编译为字节码的时候又需要符合 JVM 规范,简单来说,前端编译器的主要任务就是负责将符合 Java 语法规范的 Java 代码转换为符合 JVM 规范的字节码文件。
2.1 javac编译器简介
本书在 1.2.2 小节中,对 Java 源码的编译结果做了一个简单介绍,那么从本章开始直至第 3 章我们就一起来深入探讨这个话题。 Java 源码的编译结果为什么不是跟 C/C++一样的本地机器指令,而是字节码呢?其实相信大家也都知道,这与 Java 与生俱来的与平台无关性是密不可分的, Java 之所以能够实现“ Write Once, Run Anywhere”(一次编译,处处运行),最主要的就是归功于字节码。简单来说,字节码就相当于是一份通用的契约,尽管不同平台上的 Java 虚拟机的实现细节不尽相同,但是它们共同执行的字节码内容却是一样的,这也就是为什么 Java 的设计者们会将 Java 的编译结果设定为具有平台通用性的字节码而非本地机器指令的目的所在。
Java 源码的编译结果屏蔽了与底层操作系统和物理硬件相关的一些特性,使得开发人员尽可能地只需关注于自身业务。因为只有这样,体系结构中立、与平台无关等特性才能够真正地构建起来,否则 Java 技术就是一门传统的静态编译型语言,而非今天的动态编译型语言。或许时至今日仍然有许多非 Java 开发人员在质疑 Java 的程序运行性能,但是请大家相信, Java 早已不再是遭人唾弃,贴上低效性能标签的一门编程语言。其实说这些话的人,大部分都并不了解 Java 技术,本书在 1.1.3 节中曾经提及过,在 JDK1.0 版本时, Java 程序的运行效率确实不尽如人意,这是因为 Java 当时的解释器非常低效,但这却并不代表 Java语言自身低效,也就是说,程序的运行性能与编程语言其实是没有多大直接关系,真正决定程序运行性能的是编译器。不过在当时,由于技术限制等原因, JVM 中只有解释器,而没有如今先进高效的 JIT 编译器,可是现在, Java 突破了这些技术限制,程序的运行性能已经达到了可以和 C/C++程序一较高下的地步,并且 Java 技术自身的诸多优势同样也是 C/C++无法比拟的,