Java程序最初都是通过解释器(Interpreter)进行解释执行的,当虚拟机发现某个方法或代码块的运行特别频繁,就会把这些代码认定为“热点代码”(Hot Spot Code),为了提高热点代码的执行效率,在运行时,虚拟机将会把这些代码编译成本地机器码,并以各种手段尽可能地进行代码优化,运行时完成这个任务的后端编译器被称为即时编译器。
解释器与编译器
当程序需要迅速启动和执行的时候,解释器可以首先发挥作用,省去编译的时间,立即运行。
当程序启动后,随着时间的推移,编译器逐渐发挥作用,把越来越多的代码编译成本地代码,这样可以减少解释器的中间损耗,获得更高的执行效率。
HotSpot虚拟机中内置了两个(或三个)即时编译器。
- 客户端编译器C1
- 服务端编译器C2
用户也可以使用“-client”或“-server”参数去强制指定虚拟机运行在客户端模式还是服务端模式。
用户也可以使用参数“-Xint”强制虚拟机运行于“解释模式”(Interpreted Mode)。
可以使用参数“-Xcomp”强制虚拟机运行于“编译模式”(Compiled Mode)。
热点代码主要有两类:
- 被多次调用的方法
- 被多次执行的循环体
要知道某段代码是不是热点代码,是不是需要触发即时编译,这个行为称为“热点探测”(HotSpot Code Detection)。
基于计数器的热点探测(Counter Based Hot Spot Code Detection)。采用这种方法的虚拟机会为每个方法(甚至是代码块)建立计数器,统计方法的执行次数,如果执行次数超过一定的阈值就认为它是“热点方法”。
在字节码中遇到控制流向后跳转的指令就称为“回边(Back Edge)”