要深入理解JVM技术,我们必须先搞清楚一个基本问题:我们日常编写的Java代码是如何被执行的呢?
让我们逐步解析这个问题。首先,假设我们已经编写了一些Java代码,这些代码通常会包含许多以“.java”为后缀的源文件,例如Hello.java,Test.java等。实际上,作为Java开发者,我们在如Eclipse、Intellij IDEA等集成开发环境(IDE)中,经常会创建和编辑这样的Java源代码文件。
现在,让我们思考一下,当我们完成这些“.java”文件的编写后,如果我们想要将这些代码部署到线上服务器上运行,我们应该怎么做呢?通常的做法是将我们的代码编译并打包成“.jar”或“.war”文件,对吗?
接下来,我们会将打包好的jar或war文件部署到线上服务器。部署的方式有很多种,但最基本的方式之一是使用诸如Tomcat这样的应用服务器来部署,或者你也可以选择手动通过执行“java”命令来运行jar文件中的代码。
为了更好地理解这个过程,我们可以参考下面的流程图来回忆这个顺序。
但是,实际上这里有一个非常关键的步骤,那就是“编译”。在我们编写好的“.java”代码进行打包的过程中,通常会将代码编译成以“.class”为后缀的字节码文件,例如“Hello.class”,“Test.class”。然后,这些以“.class”为后缀的字节码文件才是可以被运行的!
在编译过程中,Java编译器会将我们编写的源代码(.java文件)翻译成计算机可以理解的字节码(.class文件)。这个过程涉及到词法分析、语法分析、语义分析和代码生成等步骤。编译后的字节码文件是一种中间代码,它不是特定于任何硬件平台的机器语言,而是可以在Java虚拟机(JVM)上执行的指令集。
通过编译,我们可以将高级语言编写的代码转换为计算机可以执行的代码,从而实现程序的运行。在编译过程中,编译器还负责检查代码中的错误,并生成相应的错误报告,帮助我们调试和修复代码中的问题。
接下来思考一个问题: 如何让编译好的".class"字节码运行起来呢? 为了实现这一目标,我们需要使用类似"java -jar"等命令来运行我们编写的代码。 当你使用"java"命令时,实际上就会启动一个JVM(Java虚拟机)进程。 这个JVM负责执行这些".class"字节码文件,相当于负责运行我们编写的系统。 因此,当我们在一台机器上部署一个系统时,一旦你启动该系统,实际上是启动了一个JVM,由它来负责运行该机器上的系统。 对于这个概念,大家一定要先理解清楚。
在继续下一步之前,我们需要了解JVM是如何运行“.class”字节码文件中的代码的。首先,JVM需要将这些“.class”文件中包含的各种类加载进来,这些“.class”文件实际上是我们编写的每一个类。
为了实现这个过程,引入了“类加载器”的概念。类加载器负责将编译好的“.class”字节码文件加载到JVM中,以便后续代码运行时使用。我们再看下图。
接下来,JVM将利用其内置的字节码执行引擎来运行已经加载到内存中的我们编写的类。
例如,如果你的代码中包含一个名为“main()”的方法,JVM将会从这个“main()”方法开始执行其中的代码。当JVM需要某个类时,它就会使用类加载器来加载相应的类。这些类都存储在以“.class”为扩展名的文件中。
本文从我们平时编写的“.java”后缀的源代码开始,逐步梳理了以下的流程:
- 将编写好的代码编译成“.class”后缀的字节码文件。
- 介绍JVM(Java虚拟机)的概念和作用。
- 探讨JVM与我们在计算机上运行的操作系统之间的关系。
- 解释类加载器的概念。
- 针对加载进内存的类进行代码的执行。
接下来,我将详细阐述以上流程:
-
在编写好“.java”后缀的源代码后,我们需要将其编译成“.class”后缀的字节码文件。这个步骤可以通过使用Java编译器(例如javac)来完成。编译后的字节码文件包含了可由Java虚拟机(JVM)执行的指令。
-
JVM是Java虚拟机的缩写,它是一个虚拟的计算机,用于执行Java字节码。JVM负责将字节码文件转换为特定平台上的机器码,并确保不同平台上的Java程序能够正确运行。
-
JVM与我们平时运行在机器上的操作系统之间存在密切的关系。JVM作为Java程序与底层操作系统之间的中间层,负责管理和控制Java程序的执行。它提供了一种独立于具体硬件平台的运行环境,使得Java程序能够在不同的操作系统上运行而无需修改源代码。
-
类加载器是JVM中的一个重要概念。它负责将字节码文件加载到内存中,并将其转化为可执行的Java类。类加载器会按照需要动态地加载类,而不是一次性将所有类加载到内存中。这样可以减少程序的启动时间和内存占用。
-
一旦类被加载进内存中,JVM就可以对其进行代码的执行。这个过程包括解释执行和即时编译两种方式。解释执行是指JVM逐行解释字节码指令并执行,而即时编译则是将热点代码(经常执行的代码片段)编译成本地机器码,以提高执行效率。
通过以上的流程梳理,我们可以更好地理解Java代码从编写到执行的整个过程,以及JVM在其中扮演的重要角色。