我对 JIT 编译器和解释器有一些疑问。 从他们的定义开始:
(解释器) 来自维基百科:
In computer science, an interpreter is a computer program that directly executes, i.e. performs, instructions written in a programming or scripting language, without previously batch-compiling them into machine language. An interpreter generally uses one of the following strategies for program execution:
1) parse the source code and perform its behavior directly
2) translate source code into some efficient intermediate representation and immediately execute this
3) explicitly execute stored precompiled code[1] made by a compiler which is part of the interpreter system
(JIT 编译器) 来自维基百科:
In computing, just-in-time compilation (JIT), also known as dynamic translation, is compilation done during execution of a program – at run time – rather than prior to execution.[1] Most often this consists of translation to machine code, which is then executed directly, but can also refer to translation to another format.
来自 StackOverFlow:
Just-in-time compilation is the conversion of non-native code, for example bytecode, into native code just before it is executed.
我有 4 个问题:
1) 常说JIT=runtime,为什么Interpreter不运行在runtime?程序运行时,解释器不会在运行时翻译和执行每一行吗?
2) 总是说 JIT 将非 native 代码翻译成 native 代码,那又如何呢?解释器不会将代码转换为 native 代码吗?如果指令未转换为 native 代码,我的进程如何执行指令?所以解释器也需要将代码翻译成本地代码。
3) 普通解释器在需要执行时翻译每一行,而使用 JIT 编译器在执行前翻译每一行,因此在需要执行该行的那一刻是可行的。不是吗?
4) 那么解释器和 JIT 编译器之间的真正区别是什么,两者都在运行时执行程序,都从中间语言翻译成本地代码......
最佳答案
解释器不会将源代码翻译成本地机器代码。虽然您的计算机只能执行机器代码,但它执行的机器代码不一定是高级语言的翻译。令人困惑?让我们看一个简单的玩具示例...
考虑具有两个功能的编程语言 PrintForPony,print
和 sleep
。 print
函数将一串字符作为其唯一参数并将其打印到标准输出,而 sleep
将正整数作为其唯一参数并使当前线程 hibernate 一段时间那段时间。 PFP 的伪 BNF:
program ::= statement_list
statement_list ::= statement | statement NEWLINE statement_list
statement ::= print STRING | sleep POSITIVE_INTEGER
这是PFP 解释器的 super 简单 Java 实现。该程序将源文件作为其唯一参数并对其进行解释:
import java.io.BufferedReader;
import java.io.FileReader;
public class PFPInterpreter {
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new FileReader(args[0]));
String line = null;
while ((line = br.readLine()) != null) {
if (line.startsWith("print ")) {
System.out.println(line.substring("print ".length()));
} else if (line.startsWith("sleep ")) {
Thread.sleep(Long.parseLong(line.substring("sleep ".length())));
} else {
throw new IllegalArgumentException("Unknown function: " + line);
}
}
}
}
示例源文件:
print Hello, World!
sleep 1000
print Goodbye, World!
和示例输出:
$ java PFPInterpreter test.pfp
Hello, World!
Goodbye, World!
在任何时候,PFP 都不会被翻译成本地机器代码。执行的 native 机器代码是 JVM,与这种玩具语言无关。我们还可以为 PFP 编写一个编译器,将代码转换为可执行文件(我不打算这样做,因为这个答案已经太长了),但问题的关键在于解释器不会编译为 native 代码 - 它读取输入文件并根据内容做一些事情。
回答问题:
1) 解释器是为您运行代码的运行时。我不确定您在哪里读到解释器在运行时不起作用,但我也不确定它应该意味着什么。
2) 如上所示,不,解释器不会转换为 native 机器代码。 JIT 编译器可以。您的处理器仅执行 native 机器代码,但该 native 机器代码可能是读取任意文件并根据内容做某事的程序。从这个意义上说,解释器实际上只是一个接受文本文件形式输入的典型程序。
3) JIT 编译相当复杂,我不是专家。然而,例如,对于 Java 的 HotSpot,代码块必须在调用 JIT 编译器之前执行一定次数(客户端 1,500 次,服务器 15,000 次,IIRC)。这可能是因为实际的编译不是免费的,而且编译的 native 代码很可能被缓存以供以后执行(这可以解释许多执行的要求)。这使得 JIT 编译成为一项投资(在时间和空间上),在第一次执行时可能不会更快(甚至可能更慢),但后续执行会更快,因为不再需要编译,本地机器代码效率更高。
4) 见上文。
希望对您有所帮助!
关于java - 关于 JIT 编译器和解释器的说明,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23417218/