为什么我们使用Java虚拟机?

Why do we use the Java virtual machine?

我正在努力思考 Java 虚拟 Machine 及其使用字节码的原因。我知道它已经被问了很多次,但不知何故我最终无法做出正确的假设,所以我研究了很多东西并决定解释我认为它是如何工作的以及它是否正确。

我了解到在C++中,编译器是在特定的(架构+操作系统)上编译源代码的。因此,针对 (x86 + Windows) 的 C++ 编译版本不会 运行 在任何其他体系结构或操作系统上。

我的假设

当Java编译器将源代码编译成字节码时,它不会根据体系结构或操作系统进行编译。如果在 Windows 或 Mac 上编译,源代码将始终被编译为 相同的 字节码。假设我们编译了,现在将字节码发送到另一台计算机 (x86 + windows)。为了让那台计算机 运行 这个字节码,它需要 JVM。现在,JVM 知道它 运行 正在使用什么架构 + 操作系统。 (x86 + windows)。因此,JVM 会将字节码编译为 x86 + Windows 并生成机器码,现在可以由实际计算机 运行

因此,即使我们使用 Java 虚拟 Machine,我们仍然 运行 操作系统上的实际机器代码,而不是虚拟机上的。虚拟 Machine 只是帮助我们将字节码转换为机器码。

这意味着在使用Java时,我们唯一需要担心的就是安装JVM,仅此而已。

我一直认为虚拟 Machine 本身就是一台计算机,它将 运行 代码放在自己独立的地方,但对于 JVM,我不认为这是正确的,因为我认为 JVM 生成的机器代码在我们拥有的实际操作系统上仍然必须是 运行。

你觉得我的假设正确吗?

编译java代码时,会创建java字节码。

此字节码与平台无关,可以由 JVM 运行。这意味着 Kotlin 等其他编程语言也可以生成此 java 字节码并以 JVM 为目标。

所以你说的 java-bytecode 对于每个平台都是一样的是正确的。

然而,您不完全正确的地方是,JVM 将 java 字节码转换为本机字节码。

JVM 改为执行 java 字节码并将指令提供给操作系统。在执行时,JVM 将一堆 java 字节码编译为本机代码,然后操作系统可以执行这些代码。这种情况在代码执行时发生,因此从未加载的 class 也永远不会被执行,也永远不会作为机器代码结束。

因此,我们可以使用 Reflection 等功能,其中 class 文件的某些 java 字节码可以在编译前的 运行 时间进行修改到本机机器代码。

JVM 基本上位于操作系统和 java 字节码之间。在某种意义上就像一个普通的虚拟机。

下面的文章对 JVM 进行了很好的可视化。

https://www.guru99.com/java-virtual-machine-jvm.html

java字节码是一种中间码形式。

该代码可以解释,JVM就是这样一个解释器模拟(模拟)每一个字节代码指令。这很慢但很容易携带。

该代码可以 编译 为本机代码,通常 JVM 包含一个即时 编译器执行。此本机代码可以针对运行所在的当前机器进行优化,本机代码不需要从文件中加载,并且可以进行代码内联。

因此,JVM 主要是 解释器 ,java 字节代码,可移植到许多平台。

上下文:

  • [其他语言]微软的C#语言更像是一个编译器.
  • [其他中间代码]LLVM IR是C端的中间代码,可编译。
  • [其他 JVM] JVM 不止一种,技术各不相同。

When Java compiler compiles the source code into bytecode, It doesn't do the compilation depending on architecture or operating system. The source code will always be compiled to the same bytecode if it's compiled on Windows or Mac.

全部正确。

Let's say we compiled and now, send the bytecode to another computer (x86 + windows). In order for that computer to run this bytecode, It needs JVM. Now, JVM knows what architecture + operating system it's running on. (x86 + windows). So, JVM will compile bytecode to x86 + windows and it will produce machine code which can be run by the actual computer now.

这大部分是正确的,但有几件事有点“不对劲”

首先,要在任何 计算机上执行字节码,您需要一个 JVM。这包括您编译字节码的计算机。

理论上 有可能设计和实现一台计算机来执行 JVM 字节码指令集作为其本机指令集。但我不知道是否有人有曾经认真考虑过这样做。那将毫无意义。性能无法与您花费数百美元购买的硬件相提并论。JVM字节码指令集设计紧凑,简单,JIT编译相对容易. 执行效率不高。)

其次,典型的 JVM 实际上以两种模式运行:

  • 它开始使用解释器在软件中执行字节码。
  • 稍等片刻后,它会选择性地将频繁使用的方​​法的字节码编译为平台的本机指令集并执行本机代码。编译是使用 JIT 编译器完成的。

请注意,JIT 编译器是特定于平台的。

So, even though, we use Java Virtual Machine, we still run the actual machine code on our operating system and not on the virtual machine.

没错。

[The Java] Virtual Machine just helps us to transform bytecode into machine code.

JVM 实际上做的更多。像这样的东西:

  • 垃圾收集
  • 字节码加载和验证
  • 实施反射
  • 提供本机代码方法以桥接 Java 类 和操作系统功能
  • 实施用于监视、分析、调试等的基础结构。

This means that when using Java, the only thing we have to worry about is installing JVM and that's it.

是的。但是在现代 JDK 中还有其他选择;例如jlink 将生成一个可执行文件,其中嵌入了精简的 JRE,因此您无需安装 JRE。并且GraalVM支持提前(AOT)编译。

I just always thought that the Virtual Machine is just a computer itself where it would run the code in its own isolated place, but in case of JVM, i don't think that's correct, because I think machine code JVM produces still has to be run on the actual operating system we have.

啊是的。

术语“虚拟机”具有多重含义:

  • A Java 虚拟机“执行”Java 字节码……在上述意义上。
  • Linux 或 Windows 虚拟机是用户应用程序和来宾操作系统 运行 在“管理程序”操作系统控制下的地方。应用程序和来宾 OS 使用本机硬件来执行指令,但它们无法完全控制硬件。
  • 并且可能还有其他含义。

如果您将 JVM 与其他类型的虚拟机混为一谈,您可能会陷入困境。不。它们差异很大,将概念混为一谈不会帮助您理解。