标签:1.2 全局 运行速度 优化 访问 范围 不能 采样 数组元素
在部分商用虚拟机中,Java程序最初是通过解释器进行解释执行的,当虚拟机发现某个方法或代码块运行地特别频繁,就会把这些代码块认定为“热点代码”,为了提高热点代码的执行效率,在运行时,虚拟机会把这些代码编译成与本地平台相关的机器码,并进行各种层次的优化,完成这个任务的编译器称为即时编译器(JIT编译器)。
解释器和编译器
当程序需要迅速启动和执行的时候,解释器可以首先发挥作用,省去编译的时间,立即执行。当程序运行后,随着时间的推移,编译器逐渐发挥作用,把越来越多的代码编译成本地代码之后,可以获取更高的执行效率。//解释执行节约内存,编译执行提升效率
解释器还可以作为编译器激进优化时的一个“逃生门”。让编译器根据概率选择一些大多数时候都能提升运行速度的优化手段,当激进优化的假设不成立时,退回解释状态继续执行。因此在整个虚拟机执行架构中,解释器和编译器经常是相辅相成配合工作的。
HotSpot虚拟机中内置了两个即时编译器,称为Client Compiler(C1编译器)和 Server Compiler(C2编译器)。HotSpot虚拟机中默认采用解释器与其中一个编译器直接配合的方式工作,程序使用哪个编译器,取决于虚拟机运行的模式,HotSpot虚拟机会根据自身版本与宿主及其的硬件性能自动选择运行模式,用户也可以使用-client或-server参数去强制指定虚拟机运行在Client模式还是Server模式。
Mixed Mode 混合模式
Interpreted Mode解释模式 -Xint 此时编译器完全不介入
Compiled Mode编译模式 -Xcomp 解释器会在编译无法进行的情况介入
编译对象和触发条件
1.运行过程中会被JIT编译的热点代码有两类
1.1 被多次调用的方法
编译器会对整个方法进行编译,这是虚拟机标准的编译方式
1.2 被多次执行的循环
编译器依然会以整个方法作为编译对象,而这种编译方式发生在方法执行过程中,所以被称为栈上替换(OSR)
2.热点探测的两种方式
2.1基于采样的热点探测,虚拟机周期性地检查各个线程的栈顶,如果发现某个方法经常出现在栈顶,就认为是“热点方法”。优点:简单高效,明确方法调用关系 缺点:容易因为线程阻塞或别的外界因素的影响而扰乱热点探测。
2.2基于计数器的热点探测,虚拟机为每个方法建立计数器,执行次数超过某个阈值,就认为是“热点方法”。优点:统计结果严谨 缺点:需要为每个方法建立并维护计数器,而且不能直接获取到方法的调用关系。
HotSpot虚拟机采用的是第二种,为每个方法准备了两个计数器:方法调用计数器以及回边计数器。这两个计数器都有一个确定的阈值,当计数器超过阈值溢出就会触发JIT编译。
编译优化技术
JDK设计团队几乎把对代码的所有优化措施都集中在了即使编译器上。所以一般来说即时编译器产生的本地代码会比javac产生的字节码更优秀。
语言无关的经典优化技术:公共子表达式消除
语言相关的经典优化技术:数组范围检查消除
最重要的优化技术之一:方法内联
最前沿的优化技术之一:逃逸分析(这项技术暂时还不成熟)
当一个对象在方法里面被定义后,它可能被外部方法所引用,这种行为称为方法逃逸。甚至还有可能被外部线程访问到,譬如赋值给类变量或可以在其他线程中访问的实例变量,这种行为称为线程逃逸。
如果能够证明一个对象不会发生逃逸,则可以为这个变量进行一些高效的优化,如:
Java与C/C++编译器的对比
Java语言的这些性能上的劣势都是为了换取开发效率上的优势而付出的代价。而且即时编译器也有静态编译器不能做的优化,由于C++编译器的静态特性,以运行期性能监控为基础的优化措施都不能进行,如调用频率预测、分支频率预测等。
标签:1.2 全局 运行速度 优化 访问 范围 不能 采样 数组元素
原文地址:http://www.cnblogs.com/luyu1993/p/7196031.html