👋了解JVM概述
⚽️什么是JVM
Java虚拟机(JVM)是一个抽象的计算机器。JVM 是一个程序,对于编写在其中执行的程序来说,它看起来就像一台机器。这样,Java 程序就可以写入同一组接口和库。针对特定操作系统的每个 JVM 实现都会将 Java 编程指令转换为在本地操作系统上运行的指令和命令。这样,Java 程序就实现了平台无关性。
Java 虚拟机的第一个原型实现是由 Sun Microsystems, Inc. 完成的,它在由类似于现代个人数字助理 (PDA) 的手持设备托管的软件中模拟了 Java 虚拟机指令集。现在 Oracle, Inc. 实现在移动、桌面和服务器设备上模拟 Java 虚拟机,但 Java 虚拟机不采用任何特定的实现技术、主机硬件或操作系统。它本身并不被解释,但也可以通过将其指令集编译为 CPU 的指令集来实现。它也可以用微代码或直接在硅中实现。
Java 虚拟机对 Java 编程语言一无所知,只知道一种特定的二进制格式,即类文件格式。类文件包含 Java 虚拟机指令(或字节码)和符号表,以及其他辅助信息。
为了安全起见,Java虚拟机对类文件中的代码施加了严格的语法和结构约束。然而,任何具有可以用有效类文件表达的功能的语言都可以由 Java 虚拟机托管。受到通用的、独立于机器的平台的吸引,其他语言的实现者可以转向 Java 虚拟机作为其语言的交付工具。
⚽️为什么需要JVM
在求职面试的过程中,面试官经常会问及JVM的相关知识,可是对于为什么需要JVM这个问题却很少提及,以我个人的编程经验和对Java的了解,尝试在这里做一个非标准答案,供大家参考。
Java 虚拟机(JVM)加载、验证和执行 Java 字节码。它被称为解释器或Java编程语言的核心,因为它执行Java编程。
JVM 专门负责将字节码转换为机器特定的代码,并且在 JDK 和 JRE 中都是必需的。它还依赖于平台并执行许多功能,包括内存管理和安全性。此外,JVM 还可以运行用其他编程语言编写并已翻译为 Java 字节码的程序。
Java 本机接口 (JNI) 通常与 JVM 一起提及。JNI 是一个编程框架,它使运行在 JVM 中的 Java 代码能够与与硬件和特定操作系统平台相关的应用程序进行通信(即调用和被调用)。这些应用程序称为本机应用程序,通常可以用其他语言编写。本机方法用于将用其他语言编写的本机代码移动到 Java 应用程序中。
⚽️JVM的优点
平台独立性
Java 的主要优势是一次编写,随处运行的概念。虽然 C/C++ 等本机语言经过编译以匹配特定平台,但 Java 代码被编译为字节码。正如我之前提到的,Java 字节码可以在多个平台上运行,只要可以在其上安装 JVM。JVM 可以将字节码指令解释为特定平台的本机语言。
具有通用 API 的运行时环境
使用 JVM 的另一个巨大好处是可以使用通用 API 来处理特定于平台的资源。例如,当 JVM 会为您处理时,您无需考虑如何在每个可能的平台上处理文件输入/输出 (I/O) 。JVM 不仅会处理特定于平台的文件 I/O,还会处理其他资源,如内存、网络、输入输出设备等。
不仅如此,还有大量的 Java 库,包括 JRE 中可用的常见库。任何 JVM 编程语言都可以访问所有这些,就好像它们是自己语言的一部分一样。
安全
Java 虚拟机允许您使用内置安全功能编写高度安全的程序。它阻止 Java 程序直接与操作系统 (OS)资源交互。可以根据特定需求配置 JVM 中的安全策略设置。例如,可以启用运行时安全沙箱。这将阻止 Java 代码读取或写入硬盘、打开网络连接或以任何其他方式与操作系统资源交互。
正确性
每次加载字节码时,JVM 都会根据 Java 虚拟机规范执行验证。它确保生成的代码由有效的编译器正确编写和编译。这是加载过程中最复杂的部分之一。执行了许多验证检查,例如根据 JVM 约束和内存分配进行验证。
内存管理
说到内存分配。无需为新创建的数组保留内存或使用指针进行操作以尝试简单地使用数组。Java 虚拟机将处理内存管理。它将为变量和对象分配所需的内存。 然后跟踪内存访问,JVM 子系统垃圾收集器 (GC)可以在适当的时候回收未使用的内存。GC 并不完美,除了它的实用性之外,它还带来了轻微的性能下降。
JVM内存管理的主要好处是开发软件时无需考虑何时分配内存以及何时释放内存。像 C 这样的非托管语言最常见的问题是由程序本身引入的内存泄漏。
不仅仅是Java
Java 并不是唯一运行在 JVM 上的编程语言。使用 JVM 的优点多于缺点。许多现代流行语言都是专门为 JVM 设计的,例如可扩展的 Scala、动态 Groovy、函数式 Closure 和 Kotlin。
⚽️JVM的缺点
表现
在 Java 虚拟机上运行的程序的执行速度比针对特定平台用本机语言编写的同等程序要慢。这是因为代码优化依赖于特定于平台的功能,例如特定的英特尔处理器优化功能。Java 字节码是系统中立的,无法针对特定硬件进行优化。
但是,JVM 的更高版本引入了一些可以提高执行性能的功能。这是即时(JIT)编译器,它将字节码编译为本机代码。然后对于重复的方法调用,它直接提供本机代码,从而提高了系统的性能。还有更多。
至少在 Web 开发中,Java 在性能上不仅仅与其他现代编程语言(例如 JavaScript 或 Ruby)相匹配,甚至超越了它们。Java 完美支持多处理器系统并允许最大限度地利用其资源。
虚拟机
是的,你没有看错。JVM 本身可能就是问题所在。Java程序完全依赖Java虚拟机来执行。JVM 总是有可能因错误而失败,无论这种可能性有多小。
“任何可能出错的事情都会出错。” - 墨菲定律
Java 虚拟机软件是按照非常高的标准生产的,并且得到多家供应商的持续支持,因此不太可能发现 JVM 错误。
内存占用
每个Java程序都需要带有JVM的Java运行时环境才能运行。JRE 占用空间很容易超出合理的可用内存量,对于智能手机等某些平台来说可能太大。这就是为什么有不同的 JRE 实现来减少内存占用。例如,每个 Android 智能手机都运行一个名为Android Runtime (AR)的 JRE 版本。需要注意的是,并非所有语言功能都受 JRE 的不同实现支持。
另一个问题是云提供商根据程序使用的资源收费。JRE 在程序之上增加了额外的内存消耗。虽然有不同的 JVM 实现以及内存占用较低的实现,但这只是性能和内存占用之间的权衡。
⚽️JVM 演变:过去、现在、未来
由于 JVM 是众所周知的运行时,具有标准化的配置、监控和管理,因此它非常适合使用Docker和Kubernetes等技术进行容器化开发。它也适用于平台即服务 (PaaS),并且有多种无服务器方法。由于所有这些因素,JVM 非常适合微服务架构。
即将推出的另一个重要功能是Project Loom,它希望将虚拟线程引入 JVM。虚拟线程能够在操作系统进程之上以更高的抽象级别实现并发。虚拟线程能够在它们之间共享内存,从而可能对编码习惯和性能产生巨大的改进。
⚽️结论
1995 年,JVM 引入了两个革命性的概念,这些概念后来成为现代软件开发的标准:一次编写,随处运行和自动内存管理。软件互操作性在当时是一个大胆的概念,但如今很少有开发人员会三思而后行。同样,我们的工程前辈必须自己管理程序内存,而我们这一代人是伴随着垃圾收集长大的。
我们可以说 James Gosling 和 Brendan Eich 发明了现代编程,但在接下来的几十年里,还有成千上万的其他人在他们的想法的基础上进行了完善和发展。Java 虚拟机最初仅适用于 Java,但如今它已经发展到支持许多脚本和编程语言,包括 Scala、Groovy 和 Kotlin。展望未来,很难想象 JVM 不会成为开发领域的重要组成部分。