暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

一文了解 JVM JDK JRE

Just do DT 2021-11-24
712

什么是JVM?

JVM 全称是 Java Virtual Machine,也就是我们耳熟能详的 Java 虚拟机。她能识别 .class 后缀的文件,并且能够解析她的指令,最终调用操作系统上的函数,完成我们想要的操作。
虚拟机:指以软件的方式模拟具有完整硬件系统功能、运行在一个完全隔离环境中的完整计算机系统 ,是物理机的软件实现。常用的虚拟机有VMWare,VirtualBox,Java Virtual Machine(Java虚拟机,简称JVM)
JVM 有如下三层含义,分别是:
  • JVM 规范要求
  • 满足 JVM 规范要求的一种具体实现(一种计算机程序)
  • 一个 JVM 运行实例,在命令提示符下编写 Java 命令以运行 Java 类时,都会创建一个 JVM 实例

为什么需要JVM?

一般情况下,使用C++开发的程序,编译成二进制文件后,就可以直接执行了,操作系统能够识别她,但是Java程序不一样,使用 javac 编译成 .class 文件之后,还需要使用 Java 命令去主动执行她,操作系统并不认识这些 .class 文件。
你可能会想,我们为什么不能像 C++ 一样,直接在操作系统上运行编译后的二进制文件呢?而非要搞一个处于程序于操作系统中间层的虚拟机呢?
这就是 JVM 的过人之处了。大家都知道,Java 是一门抽象程度特别高的语言,提供了自动内存管理等一系列的特性。这些特性直接在操作系统上实现是不太可能的,所以需要 JVM 进行一系列的转换。根据前面的介绍,我们可以做如下的类比。
  • JVM:等同于操作系统
  • Java 字节码:等同于汇编语言
Java 字节码对于JVM而言, 一般都比较容易读懂,这从侧面上证明了 Java 语言的抽象程度高。你可以把 JVM 认为是一个翻译器,会持续不断的翻译执行 Java 字节码,然后调用真正的操作系统函数,这些操作系统函数是与平台息息相关的。
如果你还是对上面的介绍有一点儿模糊的话,可以参考下图。

从图中可以看到,有了 JVM 这个抽象层之后,Java 就可以实现跨平台了。JVM 只需要保证能够正确执行 .class 文件,就可以运行在诸如 Linux,Windows、MacOS 等平台上了。而 Java 跨平台的意义在于一次编译,到处执行,能够做到这一点儿 JVM 功不可没。比如我们在 Maven 仓库下载同一版本的 jar 包就可以到处运行,不需要在每个平台上再编译一次。
现在的一些 JVM 扩展语言,比如 Scala,JRuby等,编译到最后都是 .class 文件,Java 语言的维护者,只需要控制好 JVM 这个解析器就可以将扩展语言无缝的运行在 JVM 之上了。
从上面可以看出,JVM 上承开发语言,下接操作系统,她的中间接口就是字节码。
而 Java 程序和我们通常使用的 C++ 程序有什么不同呢?请看下图。

对比上面的两张图可以看到 C++ 程序是编译成操作系统能够识别的 .exe 文件,而 Java 程序是编译成 JVM 能够识别的 .class 文件,然后由 JVM 负责调用系统函数执行程序。

什么是JRE?

通过上面的学习,我们了解到了 JVM 是 Java 程序能够运行的核心。但是需要注意的是,JVM 离开了 .class 文件,什么也无法干。因此,你需要给 JVM 提供 .class 文件。
注意:仅仅是 JVM,是无法完成一次编译,到处运行的。她需要一个基本的类库,比如怎么操作文件,怎么连接网络等。而 Java 会一次性地将 JVM 运行所需要的类库都传递给她。JVM 标准加上实现的一大堆基础类库,就组成了 Java 的运行时环境,也就是我们常说的 JRE(Java Runtime Environment)。有了 JRE 之后,我们的 Java 程序便可以在浏览器中运行了。大家可以看一下自己安装的 Java 目录,如果是只需要执行一些 Java 程序,只需要一个 JRE 就足够了。

什么是JDK?

JDK(Java Development Kit) 是用于开发 Java 应用程序的软件开发工具集合,包括了 Java 运行时的环境(JRE)、解释器(Java)、编译器(Javac)。对于 JDK 来说,比 JRE 更庞大了一些,它是 Java 开发的核心。

JDK 中包含了哪些内容?

  • JDK 是提供给 JAVA 开发人员使用的,其中包含了 Java 的开发工具,也包括了 JRE。所以安装了 JDK,就不用在单独安装 JRE 了。其中的开发工具:编译工具(javac),打包工具(jar)等。
  • JRE(Java Runtime Environment)Java 运行环境:包括 Java 虚拟机(JVM Java Virtual Machine)和 Java 程序所需的核心类库等,如果想要运行一个开发好的 Java 程序,计算机中只需要安装 JRE 即可。

JDK、JRE、JVM之间的关系

就范围来说,JDK > JRE > JVM,如下图所示。
  • JDK = JRE + 开发工具
  • JRE = JVM + 类库

JVM,JRE,JDK在开发运行 Java 程序时的交互关系

简单来说,就是通过 JDK 开发的程序,编译之后,可以打包分发给其他装有 JRE 的机器上去运行。而运行的程序,就是通过 Java 命令启动的一个 JVM 实例,代码逻辑的执行都运行在这个 JVM 实例上。

Java 程序的开发运行过程为

我们利用 JDK(调用 Java API)开发 Java 程序,编译成字节码或者打包程序。然后可以用 JRE 启动一个 JVM 实例,加载、验证、执行 Java 字节码文件以及依赖库,运行 Java 程序。而 JVM 将程序和依赖库的 Java 字节码解析并变成本地代码执行,产生结果。

Java 虚拟机规范与 Java 语言规范的关系

我们通常谈到 JVM,首先会想到它的垃圾回收器,其实它还有很多部分,比如对字节码进行解析的执行引擎等。广义上来讲,JVM 是一种规范,它是最为官方、最为准确的文档;狭义上来讲,由于我们使用 Hotspot 更多一些,我们一般在谈到这个概念时,会将它们等同起来。
如果再加上我们平常使用的 Java 语言的话,可以得出下面这样一张图。这是 Java 开发人员必须要搞懂的两个规范。

左半部分是 Java 虚拟机规范,其实就是为输入和执行字节码提供一个运行环境。右半部分是我们常说的 Java 语法规范,比如 switch、for、泛型、lambda 等相关的程序,最终都会编译成字节码。而连接左右两部分的桥梁依然是 Java 的字节码。
如果 .class 文件的规格是不变的,这两部分是可以独立进行优化的。但 Java 也会偶尔扩充一下 .class 文件的格式,增加一些字节码指令,以便支持更多的特性。
你可能会有疑问,如果我不学习 JVM,会影响我写 Java 代码么?理论上,这两者没有什么必然的联系。它们之间通过 .class 文件进行交互,即使你不了解 JVM,也能够写大多数的 Java 代码。
但是,如果你想要写一些比较精巧、效率比较高的代码,就需要了解一些执行层面的知识了。了解 JVM,主要用在调优以及故障排查上面,你会对运行中的各种资源分配,有一个比较全面的掌控。

Java 程序如何运行起来的?

如下的示例代码:
public class HelloWorld {


public static void main(String[] args) {


System.out.println("Hello World");


}


}

这里的 Java 程序是文本格式的。比如下面这段 HelloWorld.java,它遵循的就是 Java 语言规范。其中,我们调用了 System.out 等模块,也就是 JRE 里提供的类库。我们可以使用 JDK 的工具 javac 进行编译后会生成 HelloWorld 字节码,Java 字节码是 JVM 与 Java 程序的桥梁,我们可以使用 JDK 自带的工具 javap 看看字节码。
0 getstatic #2 <java/lang/System.out>


3 ldc #3 <Hello World>


5 invokevirtual #4 <java/io/PrintStream.println>


8 return

最后,我们可以用如下的图来总结一下 Java 程序是如何运行的。


文章转载自Just do DT,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论