关于传统解释器,编译器和JIT编译器/解释器(JAVA)的说明

时间:2014-12-08 12:21:14

标签: java compilation interpreter jit

我学习Java并且跟随事情对我来说有点混乱。我理解的是:

Java编译器 - > Java编译器只是将.java程序转换为.class文件,  这意味着将我们的源代码转换为字节代码(它是虚拟机(JVM)的操作码代码列表,它使java,平台独立)。
Java Interpreter-&gt; 仅仅&#34;解释&#34;代码和不会将其转换为本机机器代码。它将每个指令逐个字节代码作为命令执行,并执行它,无论同一条指令发生多少次。(这就是为什么它慢,java引入JIT概念。)< BR />

JIT编译器 - &gt; 这也在执行时出现.JIT能够通过缓存已经 TRANSLATED 的代码块的结果来提高性能 - 比较每次发生时,只需重新评估字节码中的每一行或操作数。

现在我有几个问题。

1。由于我的物理处理器只了解原生机器代码如何使用JVM的解释器执行java程序,因为解释器不会将字节代码转换为本机代码。直到有人放置机器代码进入内存,物理处理器无法执行它。

2。假设不知何故,解释器还将ByteCode转换为本机机器代码,然后通过缓存(JIT)和逐行执行(解释器)&#34;执行代码块执行。是唯一区分JIT和解释器的东西?

3. 如果在执行时,JIT将字节码转换为本机代码(用于执行程序),为什么java没有提前使用java编译,如生成JVM依赖字节码之后(这反过来使java Plateform独立),将它带到目标机器(我们想要执行它)上,然后将其转换为本机机器代码(如C编译一样制作.exe或.out等)。这可能是可能的,因为我们在每个系统上都有一个特定的JVM。这比使用JIT要快得多,因为它需要花费一些时间来编译/加载程序,并且它仍然是平台独立的,只需分发Bytecode(在最终生成之前生成)从Bytecode到M / c Code的翻译。)

如果这是一个愚蠢的问题,请原谅我。

2 个答案:

答案 0 :(得分:4)

免责声明:将所有这些都带上一粒盐;它过于简单了。

1:你是对的,因为计算机本身并不了解代码,这就是JVM本身需要的原因。让我们假装XY意味着&#34;在堆栈中添加前两个元素并推送结果&#34;。然后JVM将实现如下:

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在计算机的本地机器代码中实现了每个单独的指令,并基本上查找每个字节码块以了解如何执行它。通过JITting代码,您可以通过省略这种解释来实现大的加速(即查找应该如何处理每个指令)。那,和优化。

2:JIT并没有真正运行代码;一切仍然在JVM中运行。基本上,JIT在适当的时候将一大块字节码转换为机器码。当JVM遇到它时,它认为&#34;哦,嘿,这已经是机器代码了!很好,现在我不必仔细检查每个字节,因为CPU自己理解它!我会把它抽出来,一切都会神奇地自行完成!&#34;。

3:是的,理论上可以以这种方式预编译代码,以避免解释和JITting的早期开销。但是,通过这样做,你会失去一些非常有价值的东西。您会看到,当JVM解释代码时,它还会保留有关所有内容的统计信息。当它然后JIT代码时,它知道不同部分的使用频率,允许它在重要的地方进行优化,使得常见的东西更快,代价是稀有东西,从而产生整体性能提升。

答案 1 :(得分:1)

  1. 最后,即使在解释器中,运行等效于字节码指令的机器代码也会间接发生。把它想象成钢琴。 CPU就像是钢琴演奏者。编辑器在一张纸上打孔,然后在钢琴上运行。使用翻译器基本上是在钢琴前面放置一个类似人的机器,他们读取乐谱并按下钢琴上的琴键。最后,同样的和弦发出声响,但还有一个额外的间接层。

  2. 是。差不多。

  3. 正如你所提到的,Java被吹捧为“编译一次,随处运行”。所以字节码是实现这一承诺的重要特征。当它到达你的计算机时它没有被编译的原因是一个实际的:编译很慢。通常,它发生在软件开发人员身上。如果您启动的每个Java应用程序都是第一次编译,那么您将等待一段时间。

    由于大多数程序没有完全运行(没有分支,你从不选择菜单项等),因此编译所需的部分通常会更快,因为它们是必需的。它还节省了磁盘空间,否则您的计算机上每个程序都有两个副本。

  4. 也就是说,你不是第一个对此感到疑惑的人,实际上有些人用Java编写程序,但是使用编译器来实际生成可执行文件。存在Java(-to-native)编译器,它们不是常见的用例,因为当时许多人使用可移植的C或C ++。

相关问题