实时(JIT)编译器做什么?

问题描述 投票:470回答:19

与非JIT编译器相比,JIT编译器具体做什么?有人可以给出一个简洁易懂的描述吗?

compilation compiler-construction jit
19个回答
481
投票

一个JIT编译器在程序启动后运行,并将代码(通常是字节码或某种VM指令)动态编译(或者只是及时调用),形成通常更快的形式,通常是主机CPU的本机指令系统。 JIT可以访问动态运行时信息,而标准编译器不能并且可以进行更好的优化,例如内联频繁使用的函数。

这与在程序首次运行之前将所有代码编译为机器语言的传统编译器形成对比。

换句话说,传统编译器在您第一次运行它之前将整个程序构建为EXE文件。对于较新的样式程序,使用伪代码(p代码)生成程序集。只有在OS上执行程序之后(例如,通过双击其图标),(JIT)编译器才会启动并生成基于Intel的处理器或其他任何人都能理解的机器代码(m代码)。


4
投票

我知道这是一个旧线程,但运行时优化是JIT编译的另一个重要部分,似乎没有在这里讨论。基本上,JIT编译器可以在程序运行时监视程序,以确定改进执行的方法。然后,它可以在运行期间动态地进行这些更改。谷歌JIT优化(javaworld有一个漂亮的good article about it.


3
投票

即时编译器(JIT)是一个软件,它接收不可执行的输入并返回要执行的相应机器代码。例如:

Intermediate representation    JIT    Native machine code for the current CPU architecture

     Java bytecode            --->        machine code
     Javascript (run with V8) --->        machine code

这样做的结果是,对于某个CPU架构,必须安装适当的JIT编译器。

差异编译器,解释器和JIT

虽然在我们想要将源代码转换为机器代码时通常会有例外,但我们可以使用:

  1. 编译器:获取源代码并返回可执行文件
  2. 解释器:按指令执行程序指令。它需要源代码的可执行段,并将该段转换为机器指令。重复此过程,直到所有源代码都转换为机器指令并执行。
  3. JIT:JIT的许多不同实现都是可能的,但是JIT通常是compliler和解释器的组合。 JIT首先通过解释将中间数据(例如Java字节码)转换为机器语言。 JIT通常可以检测代码的某个部分何时经常执行,并且将编译此部分以便更快地执行。

2
投票

Jit代表及时编译器jit是一个程序,它将java字节代码转换为可以直接发送到处理器的指令。

在特定系统平台上使用java及时编译器(实际上是第二个编译器)将字节码符合特定系统代码,一旦代码被jit编译器重新编译,它通常会在计算机中更快地运行。

即时编译器随虚拟机一起提供,可选择使用。它将字节码编译为立即执行的特定于平台的可执行代码。


1
投票

非JIT编译器获取源代码并在编译时将其转换为机器特定的字节代码。 JIT编译器获取在编译时生成的机器不可知字节代码,并在运行时将其转换为机器特定的字节代码。 Java使用的JIT编译器允许单个二进制文件在多个平台上运行而无需修改。


1
投票

实时(JIT)编译(也称为动态转换或运行时编译)是一种执行计算机代码的方法,该代码涉及程序执行期间的编译 - 在运行时 - 而不是在执行之前。

IT编译是两种传统的机器代码转换方法的组合 - 提前编译(AOT)和解释 - 并结合了两者的优点和缺点。 JIT编译将编译代码的速度与解释的灵活性相结合。

让我们考虑JVM中使用的JIT,

例如,HotSpot JVM JIT编译器生成动态优化。换句话说,他们在Java应用程序运行时做出优化决策,并生成针对底层系统架构的高性能本机机器指令。

当选择一种方法进行编译时,JVM将其字节码提供给即时编译器(JIT)。在正确编译方法之前,JIT需要理解字节码的语义和语法。为了帮助JIT编译器分析该方法,它的字节码首先在一个称为跟踪树的内部表示中重新构造,它比字节码更接近机器代码。然后对该方法的树执行分析和优化。最后,树被翻译成本机代码。

跟踪树是在编程代码的运行时编译中使用的数据结构。跟踪树用于一种“及时编译器”,它跟踪在热点期间执行的代码并对其进行编译。请参阅this

参考:


0
投票

80%的时间使用20%的字节代码。 JIT编译器获取这些统计信息并通过添加内联方法,删除未使用的锁等以及创建特定于该机器的字节码来优化这20%的字节代码以更快地运行。我引用这篇文章,我发现它很方便。 http://java.dzone.com/articles/just-time-compiler-jit-hotspot


0
投票

JIT指的是少数JVM实现中的执行引擎,一个更快但需要更多内存的实时引擎,是一个即时编译器。在此方案中,方法的字节码在第一次调用方法时被编译为本机机器代码。然后缓存该方法的本机机器代码,以便下次调用相同方法时可以重用它。


0
投票

出于性能原因,JVM实际上在运行时执行编译步骤。这意味着Java没有干净的编译 - 执行分离。它首先执行从Java源代码到字节码的所谓静态编译。然后将此字节码传递给JVM以供执行。但是执行字节码很慢,因此JVM测量字节码的运行频率,当它检测到频繁运行的代码“热点”时,它会执行从“热点”代码(热点分析器)的字节码到机器代码的动态编译。今天有效的Java程序是由机器码执行运行的。


243
投票

最初,编译器负责将高级语言(定义为高于汇编程序的语言)转换为目标代码(机器指令),然后将其(通过链接器)链接到可执行文件中。

在语言发展的某一点上,编译器会将高级语言编译成伪代码,然后由解释器解释它来运行程序。这消除了目标代码和可执行文件,并允许这些语言可移植到多个操作系统和硬件平台。 Pascal(编译为P-Code)是第一个; Java和C#是最近的例子。最终,术语P-Code被字节码替换,因为大多数伪操作都是一个字节长。

Just-In-Time(JIT)编译器是运行时解释器的一个特性,它不是在每次调用方法时解释字节码,而是将字节码编译成正在运行的机器的机器代码指令,然后调用它目标代码。理想情况下,运行目标代码的效率将克服每次运行时重新编译程序的低效率。


66
投票

JIT-及时这个词本身就说需要(按需)

典型场景:

源代码完全转换为机器代码

JIT场景:

源代码将转换为汇编语言,如结构[对于C#的ex IL(中间语言),对于java的ByteCode]。

仅当应用程序需要所需的代码仅转换为机器代码时,中间代码才转换为机器语言。

未获奖的蛋糕:

  • 在JIT中,并非所有代码都转换为机器代码,首先将必要的代码的一部分转换为机器代码,然后如果调用的方法或功能不在机器中,那么将转换为机器代码......它减少了CPU的负担。
  • 由于机器代码将在运行时生成.... JIT编译器将生成针对运行机器的CPU架构进行优化的机器代码。

JIT示例:

  1. 在Java中JIT是在JVM(Java虚拟机)中
  2. 在C#中它是在CLR(公共语言运行时)
  3. 在Android中,它是新版本的DVM(Dalvik虚拟机)或ART(Android RunTime)。

25
投票

正如其他人所说

JIT代表Just-in-Time,这意味着代码在需要时编译,而不是在运行时之前编译。

只是为了向上面的讨论添加一点,JVM维护一个函数执行时间的计数。如果此计数超过预定义的限制,JIT会将代码编译为机器语言,这可以由处理器直接执行(与javac将代码编译为字节码然后java的正常情况不同 - 解释器逐行解释此字节码将其转换为机器代码并执行)。

此外,下次计算该函数时,再次执行相同的编译代码,而不同于正常解释,其中代码被逐行地再次解释。这使得执行更快。


11
投票

JIT编译器仅在首次执行时将字节代码编译为等效的本机代码。每次连续执行时,JVM仅使用已编译的本机代码来优化性能。

enter image description here

如果没有JIT编译器,JVM解释器会逐行转换字节代码,使其看起来好像正在执行本机应用程序。

enter image description here

Source


9
投票

JIT代表Just-in-Time,这意味着代码在需要时编译,而不是在运行时之前编译。

这很有用,因为编译器可以生成针对您的特定计算机优化的代码。像普通的C编译器一样,静态编译器会将所有代码编译到开发人员机器上的可执行代码中。因此,编译器将基于某些假设执行优化。它可以更慢地编译并进行更多优化,因为它不会减慢用户执行程序的速度。


9
投票

在Java编译器生成字节代码(体系结构中立)之后,执行将由JVM(在Java中)处理。字节代码将由加载器加载到JVM中,然后解释每个字节指令。

当我们需要多次调用一个方法时,我们需要多次解释相同的代码,这可能需要更多的时间。所以我们有JIT(即时)编译器。当字节被加载到JVM(其运行时)时,整个代码将被编译而不是解释,从而节省时间。

JIT编译器仅在运行时工作,因此我们没有任何二进制输出。


7
投票

即时编译器(JIT): 它将java字节码编译为该特定CPU的机器指令。

例如,如果我们在java代码中有一个循环语句:

while(i<10){
    // ...
    a=a+i;
    // ...
 }

如果i的值为0,则上述循环代码运行10次。

由于同一条指令要执行10次,因此无需一次又一次地编译字节码10次。在这种情况下,有必要仅编译该代码一次,并且可以将值更改所需的次数。因此,Just In Time(JIT)编译器会跟踪这些语句和方法(如上所述),并将这些字节代码编译成机器代码以获得更好的性能。

另一个类似的例子是在字符串/句子列表中使用“正则表达式”搜索模式。

JIT编译器不会将所有代码编译为机器代码。它编译在运行时具有类似模式的代码。

请参阅此Oracle documentation on Understand JIT以了解更多信息。


4
投票

你有一些代码被压缩成一些IL(中间语言)。运行程序时,计算机无法理解此代码。它只能理解本机代码。因此,JIT编译器可以动态地将您的IL编译为本机代码。它在方法级别执行此操作。

© www.soinside.com 2019 - 2024. All rights reserved.