# 给Java字节码加上”翅膀“的JIT编译器
上面文章在介绍Java的内存模型的时候,提到过由于编译器的优化会导致重排序的问题,其中一个比较重要的点地方就是关于JIT编译器的功能。JIT的英文单词是Just In Time翻译成中文就是及时,恰好的意思,意在说明JIT编译器优化java的class文件里面的byte code是拿捏的恰到好处。
JIT编译器是JRE里面的一个为了在运行时提升Java程序性能的一个重要组件,我们知道Java代码一大优势就是在于一次编写,到处运行的特点。Java程序通常在编译后是一大堆class文件,也就是我们所说的字节码,然后通过JVM来解释执行这些与平台无关的字节码,从而屏蔽了操作系统的差异,做到了跨平台的特点。但jvm在在运行时候执行class文件的字节码的时候性能并没有执行跟操作系统直接有关的机器指令性能来的快,正是因为这个原因,才出现JIT编译器,目的就是为了提高执行效率。
到这里,我们再总结下JIT编译器的定义:
==在Java程序运行时把一些class文件的字节码给转变成操作系统本地的指令码,从而提升程序性能。==
如下图:
在上面的图我们能够看到,我们的java源文件先在编译时被转成class字节码文件,然后在运行时会在当一个方法第一次调用时会被JIT再次编译优化转成native machine code也就是上面说的操作系统级别的指令。
这里面大家注意到仅仅当方法第一次调用时才会进行JIT优化,那么有个问题是既然JIT编译器优化运行时执行性能,为啥不把所有的方法都优化一次呢,而非得时用到的时候才优化呢? 这正是just in time写照。 当JVM启动时候,实际上是会加载数千个方法的,理论上把所有方法都提前通过JIT转换一下是会提升更多运行性能,但实际情况是JIT编译优化是需要耗费一定的cpu和内存资源(用来缓存指令),这也意味着如果直接优化所有方法,有可能导致jvm启动的非常慢,即使它能在运行时带来的一定的性能提升。
此外,JIT在运行时做编译优化是需要重新理解字节码的语义的,为了分析方法,它的字节码会被转成一种叫做trace tree的数据结构,然后根据方法的trace tree来做相关分析和优化,最终字节码会被转成本地的机器码。当然JIT会使用多线程来编译task,从而使java应用程序也就是jvm启动的更快。到这里相信看了我上篇文章的同学们,就会明白重排序的问题。
*你看到的代码顺序,未必是其执行顺序*
这其实就是因为JIT在底层编译优化的时候为了提升编译的性能,是会把字节码放到多个线程里面的执行的,当然这里面必须保证单线程JIT优化不影响最终结果的逻辑,这就是后面会提到的关于 happend-before的约束。
最后我们来看下JIT编译优化的包括几个方面:
(1)代码内联 (合并trace tree里面小的方法)
(2)本地优化(本地分析和优化代码的一小部分,通常使用静态编译器)
(3)控制流优化(重新排列控制流的代码路径进行优化)
(4)全局优化(对整个方法进行优化)
(5)本地字节码生成(根据不同的操作系统,生成对应优化的本地机器码)
总结:
本篇文章主要介绍了Java里面JIT编译器相关的内容,通过学习我们应该认识到Java编译的字节码方法并不一定是直接就运行的,更多时候是会以 “延迟加载” 形式通过JIT优化,这样把Java字节码转成本地的机器码能更多的提升程序运行效率。
有什么问题可以扫码关注微信公众号:我是攻城师(woshigcs) 路漫漫其修远兮,吾将上下而求索
分享到:
相关推荐
——学习参考资料:仅用于个人学习使用! 本代码仅作学习交流,切勿用于商业用途,否则后果自负。若涉及侵权,请联系,会尽快处理! 未进行详尽测试,请自行调试!
ZetaVM一个用于动态编程语言的虚拟机和JIT编译器
llvmlite, 用于编写JIT编译器的轻量级 LLVM python 绑定 llvmlite 用于编写JIT编译器的轻量级 LLVM python 绑定旧的绑定公开了很多 LLVM,但是把C -style内存管理映射到 python 是容易出错的。 Numba 和许多JIT...
Minijit - 用C 和Python中从头开始编写的教育目的x86-64 JIT编译器
rbpf:用于eBPF程序的Rust虚拟机和JIT编译器
一种针对JavaScript引擎JIT编译器的模糊测试方法.pdf
——学习参考资料:仅用于个人学习使用! 本代码仅作学习交流,切勿用于商业用途,否则后果自负。若涉及侵权,请联系,会尽快处理! 未进行详尽测试,请自行调试!
luajit, LuaJIT是用于Lua语言的JIT编译器 LuaJIT 2.0.3自述文件LuaJIT是用于Lua编程语言的Just-In-Time ( JIT ) 编译器。项目主页:http://luajit.org/LuaJIT版权所有( C ) 2005 -2014 Mike Pa
如何编写JIT编译器首先,您可能不想这么做。 JIT,或更准确地说是“动态代码生成”,通常不是优化项目的最有效方法,而通用技术最终会牺牲很多可移植性,并且需要相当详细的有关处理器级优化的知识。 就是说,尽管...
HotSpot JIT编译器的日志分析器和可视化工具。 JITWatch 视频介绍 我在JITWatch 上的LJC闪电演讲中的 有关说明和屏幕截图,请参见Wiki。 JITWatch用户界面是使用JavaFX构建的。 这包含在Oracle JDK中。 如果您...
GraalVM是一个基于Oracle Labs的项目,为JVM开发了一个新的JIT编译器和Polyglot运行时。
CoreCLR是.NET Core的运行时,包括垃圾收集器、JIT编译器、原始数据类型和低级类
不需要下载源码编译执行,可以直接运行jar文件 运行命令:java -jar jitwatch.jar
CLR只执行本机的机器代码。有两种方式产生本机的机器代码:实时编译和预编译方式。...只有当要调用某个方法时,JIT编译器才会将CIL的方法体编译为相应的本机机 器码版本。这样可以优化程序的工作集。
简单的 JIT 编译器该项目旨在说明JIT编译器开发中使用的机制。使用C++ 通过 g++: g++ jit.cpp -o jit-cpp./jit-cppC 通过 gcc: gc jit.c -o jit-c./jit-c注意:如果您在编译器上启用-m32标志,这也有效。 (例如:...
JIT 编译器中的任何故障通常都需要理解正在编译的字节码序列。 迄今为止,工程师一直通过研究和理解字节码来理解方法结构。 这个过程很乏味,而且会减慢调试的速度。 如果该方法的结构非常容易获得,则可以加快问题...
《Java虚拟机精讲》以极其精练的语句诠释了HotSpot VM 的方方面面,比如:字节码的编译原理、字节码的内部组成结构、通过源码的方式剖析HotSpot VM 的启动过程和初始化过程、Java 虚拟机的运行时内存、垃圾收集算法...
本书以极其精练的语句诠释了HotSpot VM 的方方面面,比如:字节码的编译原理、字节码的内部组成结构、通过源码的方式剖析HotSpot VM 的启动过程和初始化过程、Java 虚拟机的运行时内存、垃圾收集算法、垃圾收集器...
用于编写JIT编译器的轻量级LLVM Python绑定 llvmlite是一个最初为量身定制的项目,使用以下方法: LLVM C ++ API所需的部分周围的小型C包装程序,这些尚未被LLVM C API公开。 围绕C API的ctypes Python包装器。 ...
说到编译,我猜你一定会想到 .java 文件被编译成 .class 文件的过程,这个编译我们一般称为...由于机器无法直接运行 Java 生成的字节码,所以在运行时,JIT 或解释器会将字节码转换成机器码,这个过程就叫运行时编译。