即时(JIT)编译器有什么作用?


Answers:


518

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

这与传统的编译器相反,传统的编译器在程序首次运行之前所有代码编译为机器语言。

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


16
与解释代码相反,解释代码可以立即开始立即运行字节码或VM指令,但是运行指令的速度比机器语言要慢。
亚伦,

3
JIT通常与解释代码一起使用,以将其转换为机器语言,但是,是的,纯解释代码(没有任何JITting)很慢。即使没有JITter的Java字节码也确实很慢。
Mark Cidade

48
不过,目标不一定是机器代码。JRuby有一个JIT编译器,它将在几次调用后将Ruby源代码编译为Java字节码。然后,在再进行两次调用之后,JVM JIT编译器将启动并将字节码编译为本地代码。
约尔格W¯¯米塔格

4
值得注意的是,正如Jörg所暗示的,JIT不一定立即被调用。通常,将对代码进行解释,直到确定值得进行JITting。由于JITting可能会引入延迟,因此如果很少使用某些代码,则不将其 JIT 进行调试可能会更快,因此快速响应比整体运行时更为重要。
亚当·贾斯基维奇

3
@ErikReppen:如果出现了新机器,则使用常规编译器为该新机器编译和优化程序可能会比JIT更快地产生结果。另一方面,针对该新机器进行了优化的JIT将能够优化在发明该新机器之前发布的代码的性能。
2013年

255

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

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

即时(JIT)编译器是运行时解释器的功能,它不是在每次调用方法时都解释字节码,而是将字节码编译为正在运行的计算机的机器代码指令,然后调用此代码。目标代码。理想情况下,运行目标代码的效率将克服每次运行时重新编译程序的效率低下的问题。


5
但是,这句话“即时(JIT)编译器是运行时解释器的功能”会引起混淆;例如- stackoverflow.com/questions/16439512/...
斯蒂芬ç

11
实际上,JIT是一个附加组件,您仍然可以使用Java的-Xint参数来禁用它,因此它只是一个功能。
Craig Trader

3
我完全不同意。JIT不是进化的-它是经典编译器的替代。
i486 2014年

1
JIT是从硬接线的机械开关到通过向智能手机说“ OK Google”来指定搜索条件的演进路径的第一步。作为Java 7/8的一部分可用的当前JIT是Java 2的一部分所具有的跨越式发展。
Craig Trader

1
@ i486-Sun / Oracle(AFAIK)从未交付过用于生成本机代码的Java经典(“提前”)编译器。有人争辩说JIT是一种替代方案……当他们认为这是从未交付的替代方案时。(我不赞成使用GCJ AOT编译器,因为这与Sun / Oracle无关,而且也不是一个完整的解决方案。现在肯定不可行。)
Stephen C

69

JIT-及时,单词本身说出何时需要(按需)

典型场景:

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

JIT场景:

源代码将被转换为汇编语言,如结构[对于C#来说,是ex IL(中间语言),对于Java是ByteCode)。

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

JIT与非JIT比较:

  • 在JIT中,并非所有代码都首先转换为机器代码,一部分必需的代码将被转换为机器代码,然后,如果所调用的方法或功能不在机器中,则将其转换为机器代码...它减少了CPU的负担。

  • 由于机器代码将在运行时生成...。JIT编译器将生成针对机器的CPU体系结构进行了优化的机器代码。

JIT示例:

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

7
JIT在支持真实泛型类型的框架中提供了一些特殊的优势;可以定义一个通用方法,该方法将能够产生无限范围的类型,每种方法都需要不同的机器代码,但只有JIT才能为实际产生的类型生成代码。相比之下,在C ++中,编译器必须为程序将要使用的所有类型生成代码。
2013年

6
JVM第一次运行时不会JIT代码。前几次,它解释字节码。然后,如果该代码足够频繁地运行,则可能决定烦扰它。
ninjalj 2014年

1
您是说Java中的JIT是JVM。但是我们已经将编译后的代码提供给JVM,不是吗?然后重新编译它,是什么意思?
Koray Tugay 2014年

@KorayTugay-我们向JVM提供字节码,并且JVM将按需将部分字节码转换为机器代码。这样可以节省资源。
Durai Amuthan.H 2015年

1
在Java中,JIT不是JVM。它只是其中的一部分。
happs

25

正如其他提到的

JIT代表即时(Just-in-Time),这意味着在需要时而不是在运行时才对代码进行编译。

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

同样,下次计算此函数时,将再次执行相同的编译代码,这与正常解释不同,在正常解释中,代码逐行再次解释。这使执行速度更快。


14

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

在此处输入图片说明

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

在此处输入图片说明

资源


1
我对JIT的解释是,它的作用类似于备忘录,其中“常用”功能被“存储”,并且避免了从Java字节码到依赖于ISA的本机代码的编译开销。如果这是正确的,为什么Java从一开始就不能完全编译为本地代码?这将减少任何类型的运行时编译并使Java对计算机“本地化”吗?
迈克尔·崔

12

JIT代表即时(Just-in-Time),这意味着在需要时而不是在运行时才对代码进行编译。

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


为什么编译后的代码没有存储在用户计算机的某个位置,所以下次运行该应用程序时,JIT不必再次重新编译它们?
omerfarukdogan's

好的观察。可以这样做,但是它是否真正受益取决于平台和应用程序的使用。JIT优化不一定与离线优化或提前优化相同,因此好处可能只是“非JITting”,这可能会或可能无济于事。
Brian Lyttle

9

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

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

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


2
加载到JVM中时,不会编译整个代码,因为关于如何进行编译的信息很少(请参阅:指南)。请记住,性能是最终目标。JIT具有选择性:监视和选择最流行的优化方法。并且它会一直这样做,直到单个方法达到最大优化级别为止。
Yaw Boakye

7

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

例如,如果我们的java代码中有一个loop语句:

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

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

不必一次又一次地编译字节码10次,因为同一条指令将执行10次。在这种情况下,仅需编译一次该代码,并且该值可以更改所需的次数。因此,Just In Time(JIT)编译器会跟踪此类语句和方法(如前所述),并将此类字节代码编译为机器代码以提高性能。

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

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

有关更多信息,请参见理解JIT上的Oracle文档


“由于同一条指令将执行10次,因此不必一次又一次地编译字节码10次”-常规编译器如何?它会编译几次吗?
TT_

4

您有被某些IL(中间语言)编译的代码。当您运行程序时,计算机不理解该代码。它只了解本机代码。因此,JIT编译器可将您的IL即时编译为本机代码。它在方法级别执行此操作。


2
你是什​​么意思“方法水平”?
Koray Tugay 2014年

4

我知道这是一个旧线程,但是运行时优化是JIT编译的另一个重要部分,这里似乎没有讨论。基本上,JIT编译器可以在程序运行时对其进行监视,以确定提高执行效率的方法。然后,它可以在运行时即时进行这些更改。Google JIT优化(javaworld上有一篇很好的文章。


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. JITJIT的许多不同实现都是可能的,但是JIT通常是编译器和解释器的组合。JIT首先通过解释将接收到的中间数据(例如Java字节码)转换为机器语言。JIT经常可以感觉到何时经常执行代码的特定部分,并且它将编译该部分以加快执行速度。

2

Jit表示即时编译器jit是将Java字节码转换为可以直接发送到处理器的指令的程序。

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

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


2

刚刚在时间(JIT)编译,(也动态翻译或运行时编译),是一个执行计算机代码的方式在执行过程中涉及编译程序的-在运行时- 而不是在执行之前

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

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

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

选择一种方法进行编译时,JVM会将其字节码提供给即时编译器(JIT)。JIT必须先了解字节码的语义和语法,然后才能正确编译该方法。为了帮助JIT编译器分析该方法,首先将其字节码重新格式化为称为跟踪树的内部表示形式,该内部表示比字节码更类似于机器代码。然后对方法的树进行分析和优化。最后,将树翻译成本地代码。

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

参考:


1

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


0

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


不知道为什么将其标记为-1。我认为这里的要点是使用运行时统计信息来帮助优化。
eze 2014年

是的,但是答案并没有这样说。从字面上看,JIT不会优化最热门的20%的代码。
mabraham 2014年

0

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


2
如果您不提供新的/更好的东西,我会避免回答这样的问题。如果您有任何反应,那可能是无礼或批评:您的答案不准确。“ JIT”不仅限于Java虚拟机,“更快但使用更多的内存”是可能的效果,但不是JIT概念所固有的,并且方法通常不是在第一次调用时就编译,而是在很明显的几次调用后才编译。总的来说,花在准时化上的时间是有利的。
zapl 2014年

0

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


0

即时编译器(也称为JIT编译器)用于提高Java的性能。默认情况下启用。它是在执行时(而不是更早)完成的。Java通过将JIT编译器包含在JVM中来普及其使用。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.