Java虚拟机(JVM)是整个Java语言体系的基石。Java虚拟机的主要责任是为开发人员提供独立于硬件平台(Hardware Independent)和操作系统(Operating System Independent)的、安全的(Secure)运行环境。因为Java虚拟机拥有众多特性,我们首先从不同视角来解读Java虚拟机的重要性与在Java生态环境中的角色,以帮助读者全方位的了解Java虚拟机的功能特点。
Java虚拟机有标准化的指令集,在运行时可以操作内存中的数据。与日常所见的服务器或者笔记本类似,服务器上的指令是在CPU上运行的;在运行时,CPU可以读取和修改内存中的数据。而Java虚拟机建立的是一个虚拟的机器;所有的指令由Java虚拟机中的“运算器”运行,运行的数据存放在内存中。因为Java虚拟机的指令已标准化,经编译,Java虚拟机可以运行任何遵守标准化指令的程序。换句话说,Java虚拟机不仅可以运行Java程序,还可以运行Scala程序,Kotlin程序,Clojure程序,Lua程序等。这些编程语言的编译器可以将其源代码转换成JVM标准指令(俗称,Java二进制代码,Java ByteCode)。
图一 Java虚拟机与服务器的比较
Java语言的一个重要特性就是一次编译、到处运行。Java虚拟机为Java程序提供了一个统一的、独立于硬件和操作系统的运行环境。在Java程序中,无论程序将会运行于什么硬件/软件环境中,开发人员面对的都是同一运行环境,例如,Java语言的字符串都是由16位字符组成的。其背后的原理是Java虚拟机承担了适配各种不同环境的职责,这包括适配数据类型宽度的不同,操作系统提供接口的不同,各种硬件环境的不同(例如:适配服务器环境,移动设备环境等)。
图二 Java虚拟机提供统一的运行环境
Java虚拟机提供了动态加载和卸载运行库的功能。在Java虚拟机初始化时,它会加载Java标准库和待运行的程序。在运行过程中,Java虚拟机还可以动态的加载额外的代码库,或者卸载不再需要的代码。因此,Java虚拟机是一个动态的运行环境。
众所周知,Java语言是先编译,后解释执行的语言。每个Java源程序(.java文件)都需要先经过编译器翻译成Java二进制代码文件(.class文件),然后,再由Java虚拟机加载并运行.class文件。整个运行的流程如下图所示。
图三 Java程序工作流程图
除了执行Java二进制代码以外,Java虚拟机还有许多其他的重要功能。我们总结如下:
因此,从上述功能可以看出,Java虚拟机有以下重要的组成部分。
因为Java虚拟机的指令集已标准化,除了我们常用的OpenJDK和Oracle JDK里的Java虚拟机,各大厂商也开发了各自的实现。例如:Eclipse OpenJ9,GraalVM,Amazon Corretto等。
从实现所使用的语言来看,绝大多数Java虚拟机是用C/C++语言实现的;然而,GraalVM是使用Java语言实现的。小水滴相信在未来会出现更多语言的实现版本(例如:go语言和rust语言)。
JRE是Java运行环境(Java Runtime Environment),它包括了Java虚拟机,Java标准库和一些其他的功能(例如:调试功能)。所以,我们可以粗略的认为JRE=JVM+Java标准库。
JIT(Just-in-Time)是一种较新的技术,其原理是:因为Java语言是解释执行的;从运行速度上看,解释执行的速度慢于直接运行相对应的机器代码。因此,JIT编译技术能够将Java二进制代码转换为等价的机器代码,用于提升Java程序的运行速度。JIT编译器是集成在Java虚拟机里的。Java虚拟机会将经常运行的代码转换成机器代码。这个转换过程是由Java虚拟机控制的,完全对开发人员或者Java程序透明。但是,JIT技术尚不成熟,编译出的机器代码也存在兼容性问题,而且,各个JVM采用了不同的实现方法。因此,本系列文章目前并不打算详细介绍其中的细节。
Java虚拟机还可以运行于调式模式中,以便于开发人员定位和调式应用程序。Java语言为调式功能指定了统一的框架和调式接口,该框架称为Java Platform Debugger Architecture(JPDA)。因为Java环境的调试框架又是一块较大的内容,我们并不打算在Java虚拟机章节中介绍。有兴趣的读者可参考JPDA文档。
我们会在后续章节中重点介绍Java虚拟机的几个重要的功能部件,以覆盖Java虚拟机的重要功能。后续章节安排如下。
注册用户登陆后可留言