问题描述
我正在学习Java,以下内容对我来说有点令人困惑。我了解的是:
I'm learning Java and the following things are a bit confusing for me. What I understood is:
-
Java编译器→Java编译器仅转换
.java
程序转换为.class
文件,这意味着将我们的源代码转换为字节码(这是虚拟机的操作码列表(
Java Compiler → The Java compiler just converts
.java
programs into.class
files, which means converting our source code into bytecode (it is a list of op codes for the virtual machine (JVM) which makes Java platform-independent).
Java Interpreter →仅解释代码,而 将其转换为本地机器代码。它将一条字节码的每条指令作为一条命令一一执行并执行,而不管同一条指令出现多少次。这就是为什么它很慢,Java引入了JIT概念。
Java Interpreter → merely "interprets" the code and does not transform it into native machine code. It executes each and every instruction of the byte code one-by-one as a command and carries it out, regardless how many time the same instruction occurs. That's why it's slow and Java introduces the JIT concept.
JIT编译器→这在执行时也会起作用。 JIT编译器可以通过缓存已翻译 的代码块的结果来提高性能,而与每次发生时仅重新评估字节码中的每一行或操作数相比,
JIT Compiler → This also comes into play at execution time. The JIT compiler is able to improve performance by caching results of blocks of code that have been translated – compared to simply re-evaluating every line or operand in the bytecode each time it occurs.
现在我有几个问题:
-
由于我的物理处理器仅理解本机代码,因此如何使用JVM的解释器执行Java程序?解释器不会将字节码转换为本地机器代码。直到并且除非有人将机器代码放入内存中,否则物理处理器将无法执行它。
As my physical processor understands only native machine code, how does a Java program get executed using the JVM's interpreter? The interpreter doesn't convert bytecode to native machine code. Until and unless someone places the machine code into memory, the physical processor won't be able to execute it.
假设这种方式,解释器还会转换字节码。到本地机器代码,那么唯一的带有缓存(JIT)的代码执行块和逐行执行(解释器)是区分JIT和解释器的唯一内容吗?
Supposing that somehow, the interpreter also converts bytecode to native machine code then a "block of code execution with caching (JIT) and line-by-line execution (interpreter)" is the only thing that differentiates the JIT and the interpreter?
如果在执行时,JIT编译器将字节码转换为本机代码(用于执行程序),那么Java为什么不使用提前编译?生成依赖于JVM的字节码(从而使Java平台独立)之后,我们可以将其带到要执行它的目标机器上,然后将其转换为本地机器代码(创建。 exe
或 .out
文件(与C编译一样)。这是可能的,因为我们在每个系统上都有一个特定的JVM。这比使用JIT编译要快得多,因为它需要花费一些时间来编译和加载程序。仅通过分配字节码(在从字节码到机器码的最终转换之前生成),它仍将与平台无关。
If, at execution time, a JIT compiler translates bytecode to native machine code (for executing the program), why doesn't Java use ahead-of-time compilation? After generating the JVM-dependent bytecode (which in turn makes Java platform-independent), we could bring it to the target machine where we want to execute it and just translate it to native machine code (creating an .exe
or .out
file as is the case with C compilation). This could be possible because we have a specific JVM on every system. This would be much faster than using JIT compilation as it takes some time compiling and loading the program. It will still be platform-independent by just distributing bytecode (generated before the final translation from bytecode to machine code).
推荐答案
免责声明:撒些盐就可以了;
Disclaimer: Take all of this with a grain of salt; it's pretty oversimplified.
1:您是正确的,因为计算机本身不理解代码,这就是为什么需要JVM本身的原因。假设 XY
的意思是将堆栈中的前两个元素相加并推入结果。然后将实现JVM,如下所示:
1: You are correct in that the computer itself doesn't understand the code, which is why the JVM itself is needed. Let's pretend XY
means "add the top two elements on the stack and push the result". The JVM would then be implemented something like this:
for(byte bytecode : codeToExecute) {
if (bytecode == XX) {
// ...do stuff...
} else if (bytecode == XY) {
int a = pop();
int b = pop();
push(a+b);
} else if (bytecode == XZ) {
// ...do stuff...
} // ... and so on for each possible instruction ...
}
JVM在计算机的本地机器代码中实现了每条单独的指令,并且看起来设置每个字节码块的执行方式。通过JIT代码,您可以通过省略这种解释(即查找应该如何处理每条指令)来实现大幅度的加速。
The JVM has, in the computer's native machine code, implemented each individual instruction and essentially looks up each chunk of bytecode for how to execute it. By JITting the code, you can achieve large speedups by omitting this interpretation (i.e. looking up how each and every instruction is supposed to be handled). That, and optimization.
2:JIT并未真正运行代码;一切仍在JVM中运行。基本上,JIT在适当的时候将字节代码块转换为机器代码。当JVM遇到它时,它会认为哦,嘿,这已经是机器代码了!亲爱的,现在,我不必再仔细检查每个字节了,因为CPU可以自己理解它!我只是
2: The JIT doesn't really run the code; everything is still run inside the JVM. Basically, the JIT translates a chunk of bytecode into machine code when appropriate. When the JVM then comes across it, it thinks "Oh hey, this is already machine code! Sweet, now I won't have to carefully check each and every byte of this as the CPU understands it on its own! I'll just pump it through and everything will magically work on its own!".
3:是的,以这种方式预编译代码,以避免早期的解释和JITting开销。但是,这样做会损失一些非常有价值的东西。您会看到,当JVM解释代码时,它还会保留有关所有内容的统计信息。然后,当它对代码进行JIT时,它知道使用不同部分的频率,从而使它可以在重要的地方对其进行优化,从而使常见的东西更快,而稀有的东西为代价,从而提高了整体性能。
3: Yes, it is possible to pre-compile code in that way to avoid the early overhead of interpretation and JITting. However, by doing so, you lose something very valuable. You see, when the JVM interprets the code, it also keeps statistics about everything. When it then JITs the code, it knows how often different parts are used, allowing it to optimize it where it matters, making the common stuff faster at the expense of the rare stuff, yielding an overall performance gain.
这篇关于关于传统解释器,编译器和JIT编译器/解释器的说明的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!