JIT 编译
Java 程序最初是仅仅通过解释器解释执行的, 即对字节码逐条解释执行, 这种方式的执行速度相对会比较慢, 尤其当某个方法或代码块运行的特别频繁时, 这种方式的执行效率就显得很低. 于是后来在虚拟机中引入了 JIT 编译器(即时编译器), 当虚拟机发现某个方法或代码块运行特别频繁时, 就会把这些代码认定为 "Hot Spot Code"(热点代码), 为了提高热点代码的执行效率, 在运行时, 虚拟机将会把这些代码编译成与本地平台相关的机器码, 并进行各层次的优化, 完成这项任务的正是 JIT 编译器.
现在主流的商用虚拟机 (如 Sun HotSpot,IBM J9) 中几乎都同时包含解释器和编译器(三大商用虚拟机之一的 JRockit 是个例外, 它内部没有解释器, 因此会有启动相应时间长之类的缺点, 但它主要是面向服务端的应用, 这类应用一般不会重点关注启动时间). 二者各有优势: 当程序需要迅速启动和执行时, 解释器可以首先发挥作用, 省去编译的时间, 立即执行; 当程序运行后, 随着时间的推移, 编译器逐渐会返回作用, 把越来越多的代码编译成本地代码后, 可以获取更高的执行效率. 解释执行可以节约内存, 而编译执行可以提升效率.
HotSpot 虚拟机中内置了两个 JIT 编译器: Client Complier 和 Server Complier, 分别用在客户端和服务端, 目前主流的 HotSpot 虚拟机中默认是采用解释器与其中一个编译器直接配合的方式工作.
运行过程中会被即时编译器编译的 "热点代码" 有两类:
被多次调用的方法.
被多次调用的循环体.
两种情况, 编译器都是以整个方法作为编译对象, 这种编译也是虚拟机中标准的编译方式. 要知道一段代码或方法是不是热点代码, 是不是需要触发即时编译, 需要进行 Hot Spot Detection(热点探测). 目前主要的热点 判定方式有以下两种:
基于采样的热点探测: 采用这种方法的虚拟机会周期性地检查各个线程的栈顶, 如果发现某些方法经常出现在栈顶, 那这段方法代码就是 "热点代码". 这种探测方法的好处是实现简单高效, 还可以很容易地获取方法调用关系, 缺点是很难精确地确认一个方法的热度, 容易因为受到线程阻塞或别的外界因素的影响而扰乱热点探测.
基于计数器的热点探测: 采用这种方法的虚拟机会为每个方法, 甚至是代码块建立计数器, 统计方法的执行次数, 如果执行次数超过一定的阀值, 就认为它是 "热点方法". 这种统计方法实现复杂一些, 需要为每个方法建立并维护计数器, 而且不能直接获取到方法的调用关系, 但是它的统计结果相对更加精确严谨.
JIT
来源: http://www.bubuko.com/infodetail-3110756.html