早期(编译期)优化
从Sun Javac代码来看,编译过程大致分为3个过程:
- 解析与填充符号表过程
- 插入式注解器的注解处理过程
- 分析与字节码生成过程
标注检查,数据及控制流分析,解语法糖,字节码生成
语法糖
- 泛型与类型擦除
- 自动装箱,拆箱与遍历循环,
- 条件编译
- 变长参数
- 内部类
- 枚举类
- 断言语句
- try中定义和关闭资源
- …
晚期(运行期)优化
java程序最初是通过解释器进行解释执行的,当虚拟机发现某个方法或代码块运行特别频繁时,就会把这些代码认定为热点代码。为了提高热点代码的执行效率,在运行时,虚拟机将会把这些代码编译成与本地平台相关的机器码,并进行各种层次的优化,完成这个任务的编译器成为即时编译器JIT
解释器与编译器
当程序需要迅速启动和执行的时候,解释器首先发挥作用,省去编译的 时间,立即执行。在程序启动后,随着时间的推移,编译器逐渐发挥作用,把越来越多的代码编译成本地代码之后,可以获取更高的执行效率。当程序运行环境中内存资源限制较大(如部分嵌入式系统中),可以使用解释执行节约内存,反之可以使用编译来提升效率。
由于及时编译器编译本地代码需要占用程序运行时间,要编译出优化程度更高的代码,所花费的时间可能更长;而且想要编译出优化程度更高的代码,解释器可能还要替编译器收集性能监控信息,这对解释执行的速度也有影响。为了在程序启动相应速度和运行效率之间达到最佳平衡,HotSpot虚拟机还会逐渐启用分层编译的策略。
运行过程中,被即时编译器编译的“热点代码”有两类:
- 被多次调用的方法
- 被多次执行的循环体
判断一段代码是不是热点代码,是不是需要触发即时编译,这样的行为称为热点探测,热点探测有两种方法:基于采样的热点探测,基于计数器的热点探测
最具有代表性的优化技术
- 语言无关的经典优化技术之一:公共子表达式消除
- 语言相关的经典优化技术之一:数组范围检查消除
- 最重要的优化技术之一:方法内联
- 最前沿的优化技术之一:逃逸分析