在 Java 启动时使用解释器执行代码省去编译的时间、立即可以运行但也造成 Java 的启动速度比较慢。在程序运行一段时间后即时编译器开始工作才是 Java 性能提升的时候,通过把 Java 代码编译成本地代码甚至在极端情况下可以媲美 C 语言的性能。
在 Java 虚拟机规范中并未要求虚拟机必须实现即时编译但即时编译在主流的虚拟机中都有实现。HotSpot 虚拟机的名字就来源于该虚拟机引以为傲的热点代码技术。
即时编译器
虚拟机执行 Java 程序时先通过解释器对代码解释执行发现某个方法或代码块执行比较频繁后,对热点代码进行编译编译后生成与本地平台相关的机器码再去执行机器码获得较高的运行效率。必要时也会通过逆优化从即时编译回到解释执行如编译器遇到罕见陷阱的情况。
虚拟机中有两个即时编译器分别为 Client Compiler 和 Server Compiler简称为 C1 编译器和 C2 编译器。
C1 编译器占用内存小、进行局部优化、代码执行效率比 C2 编译器低、适用于客户端应用; C2 编译器占用内存大、进行全局优化、代码执行效率比 C1 编译器高、适用于服务端应用。
回边计数器则统计了循环体执行的绝对次数它的阈值可以由方法调用计数器的阈值计算出来。如果回边计数器发生溢出也会把方法调用计数器调整为溢出。
调用方法时如果两个计数器之和超过了方法调用计数器的阈值就会提交方法的编译请求。循环体执行时如果两个计数器之和超过了回边计数器的阈值也是编译代码块所在的方法,因为此时方法正在执行中又被称为栈上替换即替换方法时方法的栈帧还在栈上。
编译器在后台进行编译即调用热点代码发现需要编译时先以解释方式继续执行向编译器发送编译请求,编译结束后下次调用时才使用编译的本地代码用户也可以通过启动参数来要求虚拟机禁止后台编译,编译结束前热点代码的执行处于阻塞状态。
阅读(1217) | 评论(0) | 转发(0) |