您的位置:首页 > 编程语言 > Java开发

Java 的平台无关性(一次编译,到处运行)如何实现?

2020-08-31 14:52 1051 查看

[TOC]

Java 的平台无关性(一次编译,到处运行)如何实现?

总所周知,通常把 Java 分为编译时运行时

对于编译时会使用到

javac
指令,将源代码编译生成字节码,并存储到对应的
.class
文件之中。举一个例子:

首先先在 IDEA 中创建一个项目创建包后编写以下代码以便进行后续的操作:

package cn.xilikeli.javabasic.bytecode;

/**
* <p>
* 示例代码
* </p>
*
* @author 踏雪彡寻梅
* @version 1.0
* @date 2020/8/9 - 21:39
* @since JDK1.8
*/
public class ByteCodeSample {
public static void main(String[] args) {
int i = 1;
i++;
System.out.println(i);
}
}

编写好代码之后,通过使用

javac
指令对该源码文件进行编译,如下图所示:

从上图中,可以看到这个类编译之后,就产生了一个

.class
文件。

对于

.class
文件,其中保存着
.java
文件翻译成的二进制字节码,也就是说 Java 类文件中的属性、方法以及类中的常量信息等都会分别存储到
.class
文件中。除此之外还会添加一个公有的静态常量属性
.class
,这个属性记录了类的相关信息,即类型信息,是 Class 类的一个实例。

class 文件存在的意义就是: 跨平台,即它为跨平台的基础。各种不同平台的虚拟机都统一使用这种相同的程序存储格式。不同平台的 JVM 解析相同的

.class
文件在不同平台上运行。

所以以上源文件编译之后生成

.class
文件之后,就可以使用
java
指令让 JVM 去解析对应的 class 文件,将里面的字节码内容加载进内存,最终转换成本操作系统能够识别的机器码去运行程序了,如下图所示:

那么 class 文件中到底放了什么东西呢,可以通过使用

javap
指令反编译
.class
文件查看其内容,
javap
是 JDK 自带的反汇编器,可以查看编译期产生的字节码,我们可以通过比较字节码和源代码,了解很多知识,例如可以了解编译器内部工作的机制,如下图所示:

上图中显示的这些指令,是真正加载 class 文件去执行时用到的虚指令。通过这些指令可以了解到程序的具体细节。这里就不再阐述了。

对于这个 class 文件,如果在其他平台上直接使用

java
指令去执行也是可以的,这也体现出了跨平台的特性,如下图所示(下图的环境为 Linux,上面示例的环境为 macOS):

了解了以上知识之后,就可以回到 Java 的平台无关性(一次编译,到处运行)如何实现 这个问题了。

通过上面的示例,对于这个问题就可以这样解释:

Java 源码首先被编译成字节码,再由不同平台上的 JVM 进行解析,编译之后在不同的平台上运行时不需要进行重新编译,Java 虚拟机在执行字节码的时候,把字节码转换成具体平台上的机器指令进行执行

对于上面的问题, 还可以衍生出这个问题: 为什么 JVM 不直接将源码解析成机器码去执行呢?

对于这个问题,可以这样看待,如果直接将源码解析成机器码去执行,那么每次执行都需要各种语法之类的检查,即检查结果不会被保留下来,都要重新编译重新分析,整体性能会受影响,做很多重复的工作。所以引入了中间字节码,能够保证在编译成字节码之后,多次执行程序不需要再经过重复的各种检查校验。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: