什么是即时(JIT)编译器呢?
与非JIT编译器相比,JIT编译器具体做什么? 有人可以给一个简洁和易于理解的描述?
JIT编译器在程序启动后运行,并且通常以快速forms(通常是主CPU的本地代码)将代码(通常是字节代码或某种虚拟机指令)编译(或者称为即时调用)指令系统。 JIT可以访问dynamic的运行时信息,而标准的编译器不会,也可以做更好的优化,比如经常使用的内联函数。
这与在程序第一次运行之前将所有代码编译为机器语言的传统编译器相反。
换句话说,传统的编译器在第一次运行之前将整个程序构build为一个EXE文件。 对于较新的样式程序,程序集是使用伪代码(p代码)生成的。 只有在执行OS上的程序后(例如双击图标),(JIT)编译器才会启动并生成基于Intel的处理器或任何其他能够理解的机器代码(m代码)。
开始时,编译器负责将高级语言(定义为高于汇编程序的级别)转换为目标代码(机器指令),然后将其链接(通过链接器)为可执行文件。
在语言发展的一个阶段,编译器会将高级语言编译成伪代码,然后解释器(会被解释器)解释为运行你的程序。 这消除了目标代码和可执行文件,并允许这些语言可移植到多个操作系统和硬件平台。 Pascal(编译成P-Code)是第一个; Java和C#是最近的例子。 最终术语P代码被replace为字节代码,因为大多数伪操作是一个字节长。
实时(JIT)编译器是运行时解释程序的一个特性,每次调用某个方法时不会解释字节码,而是将字节码编译到正在运行的机器的机器码指令中,然后调用目标代码。 理想情况下,运行目标代码的效率将克服每次运行时重新编译程序的低效率。
JIT-就在这个词本身就说明什么时候需要(按需)
典型场景:
源代码完全转换为机器码
JIT场景:
源代码将被转换成汇编语言,如结构[用于C#的ex IL(中间语言),用于java的ByteCode]。
只有当应用程序需要时,中间代码才被转换为机器语言,即所需的代码只被转换为机器代码。
JIT与非JIT的比较:
-
在JIT中,并不是所有的代码都会先转换成机器代码,那么必要的代码的一部分就会被转换成机器代码,那么如果一个被调用的方法或function不在机器中,那么这个代码就会变成机器代码。 CPU的负担。
-
由于机器代码将在运行时生成…. JIT编译器将生成针对运行机器CPU体系结构进行了优化的机器代码。
JIT例子:
- 在Java中JIT是在JVM(Java虚拟机)
- 在C#中它是在CLR(公共语言运行时)
- 在Android中,它是在新版本的DVM(Dalvik虚拟机)或ART(Android RunTime)中。
正如其他人所说的
JIT代表Just-in-Time,意思是代码在需要时被编译,而不是在运行之前。
只是为上面的讨论添加一个观点,JVM维护一个函数执行多less次的计数。 如果这个计数超过了预定义的限制JIT将代码编译成可以直接由处理器执行的机器语言(与javac将代码编译成字节码然后java编译的正常情况不同 – 解释器逐行解释这个字节代码将它转换成机器代码并执行)。
下一次计算这个函数的时候,同样的编译代码会被再次执行,而不像正常的解释那样,代码被逐行解释。 这使得执行速度更快。
JIT代表Just-in-Time,意思是代码在需要的时候被编译,而不是在运行之前。
这是有益的,因为编译器可以生成针对您的特定机器进行了优化的代码。 和普通的C编译器一样,静态编译器会将所有代码编译到开发者机器上的可执行代码中。 因此,编译器将根据一些假设执行优化。 它可以编译得更慢,做更多的优化,因为它不会减慢用户程序的执行速度。
在Java编译器生成字节码(这是架构中立的)之后,执行将由JVM(以Java)处理。 字节码将由加载程序加载到JVM,然后解释每个字节指令。
当我们需要多次调用一个方法时,我们需要多次解释相同的代码,这可能需要比所需的更多的时间。 所以我们有JIT(即时)编译器。 当字节被加载到JVM(运行时)时,整个代码将被编译而不是被解释,从而节省时间。
JIT编译器只在运行时工作,所以我们没有任何二进制输出。
即时编译器(JIT):
它将java字节码编译成特定CPU的机器指令。
例如,如果我们在我们的java代码中有一个循环语句:
while(i<10){ // ... a=a+i; // ... }
如果i的值为0,上面的循环代码运行10次。
当相同的指令要执行10次时,不需要一次又一次编译字节码10次。 在这种情况下,只需要编译一次该代码,并且可以将该值更改为所需的次数。 因此,Just In Time(JIT)编译器会跟踪这些语句和方法(如上所述),并将这些字节代码编译成机器代码以获得更好的性能。
另一个相似的例子是,在string/句子列表中使用“正则expression式”来search模式。
JIT编译器不会将所有代码编译为机器码。 它编译运行时具有相似模式的代码。
了解更多信息,请参阅了解了解JIT的Oracle文档 。
我知道这是一个旧的线程,但运行时优化是JIT编译的另一个重要部分,这里似乎没有讨论。 基本上,JIT编译器可以在运行时监视程序,以确定改进执行的方式。 然后,它可以在运行期间进行这些更改。 谷歌JIT优化(javaworld有一个相当不错的文章。 )
你有编译成一些IL(中间语言)的代码。 当您运行您的程序时,计算机不理解此代码。 它只懂本地代码。 所以JIT编译器可以将你的IL编译成本地代码。 它在方法级别执行此操作。
Jit代表即时编译器jit是一个将java字节码转换为可以直接发送到处理器的指令的程序。
在特定系统平台上使用Java即时编译器(真正的第二个编译器)将字节码合并到特定的系统代码中,一旦代码由jit编译器重新编译,它通常会在计算机上更快地运行。
即时编译器随虚拟机一起提供,并可供select使用。 它将字节码编译为立即执行的特定于平台的可执行代码。
非JIT编译器在编译时将源代码转换为机器特定的字节码。 JIT编译器会在编译时生成机器不可知的字节码,并在运行时将其转换为机器特定的字节码。 Java使用的JIT编译器允许单个二进制文件在多个平台上运行,而无需修改。
以下代码示例显示了JIT如何优化Java代码。
优化前的代码
class A { B b; public void newMethod() { y = b.get(); ...do stuff... z = b.get(); sum = y + z; } } class B { int value; final int get() { return value; } }
优化后的代码
class A { B b; public void newMethod() { y = b.value; ...do stuff... sum = y + y; } } class B { int value; final int get() { return value; } }
本来,代码包含两个调用b.get()方法。 优化之后,这两个方法调用被优化成单个可变复制操作; 也就是说,优化的代码不需要执行方法调用来获取类B的字段值。
20%的字节码是80%的时间。 JIT编译器获取这些统计信息并优化这20%的字节代码,以通过添加内联方法,去除未使用的锁等来创build特定于该机器的字节码,从而加快运行速度。 我从这篇文章引用,我发现它很方便。 http://java.dzone.com/articles/just-time-compiler-jit-hotspot
JIT指的是less数JVM实现中的执行引擎,速度更快但需要更多内存,是一个即时编译器。 在这个scheme中,方法的字节码在第一次被调用时被编译为本机机器码。 然后caching该方法的本机机器码,以便下一次调用同一方法时可以重新使用该机器码。
由于性能原因,JVM实际上在运行时执行编译步骤。 这意味着Java没有一个干净的编译执行分离。 它首先进行从Java源代码到字节码的所谓静态编译。 然后这个字节码被传递给JVM执行。 但是执行字节码是很慢的,所以JVM测量字节码运行的频率,当它检测到一个频繁运行的代码的“热点”时,它执行从字节码到“热点”代码(热点分析器)的机器码的dynamic编译。 如今有效的Java程序是由机器码执行的。