一、编译期优化
1.JIT编译器在运行期的优化过程对程序运行很重要,而编译期优化过程对于程序编码关系更密切
2.Javac编译器编译过程
- 解析与填充符号表过程:词法语法分析、填充符号表
- 插入式注解处理器的注解处理过程:通过注解处理器提供的标准API在编译期对注解进行处理
- 分析与字节码生成过程:标注检查、数据及控制流分析、解语法糖、字节码生成
3.语法糖
- 泛型与类型擦除
Class文件中,只要是描述不完全一致的方法即可共存,但是方法重载要求具备不同的特征签名(不包括返回值)
List<String>与List<Integer>在类型擦除后是同一个类型,擦除只是对方法的Code属性中的字节码擦除,实际上元数据还是保留了泛型信息,如此可以使用反射获取参数化类型
- 自动装箱、拆箱与遍历循环
二、运行期优化
- 解释器与编译器的交互
- 分层编译
1)第0 层
2)第1层
3)第2层
1.触发条件(热点代码)
- 被多次调用的方法:JIT标准编译方式,以整个方法作为编译对象
- 被多次执行的循环体:虽然是循环体,但是仍然编译整个方法,由于创建栈帧执行,故称为栈上替换OSR编译(On Stack Replacement)
2.热点代码探测
- 基于采样点:定期检查栈顶,若常出现,则为热点方法
- 基于技术器:为每个方法或者代码块创建计数器,统计次数是否超过阈值
3.HotSpot虚拟机:
- 方法调用计数器:AIMD
- 回边计数器:
3.编译过程
- Client Compiler:三步
- Server Compiler:会进行更多的优化动作,如无用代码消除、循环展开、公共子表达式清除等
4.编译优化技术
- 公共子表达式消除
- 数组范围检查消除
- 方法内联(重要)
目的:1)避免建立栈帧消耗 2)为其他优化建立基础
Java虚方法:引入CHA(Class Hierarchy Analysis)分析类方法的实现,如果唯一,则可以内联,但是需要逃生门,如果加载了导致继承关系变化,则抛弃已编译代码,进行解释执行或者重新编译
- 逃逸分析:方法中的对象作为参数传递给其他方法称为方法逃逸,如果能证明一个对象不会逃逸到方法或者线程之外,则可对这个变量进行一些高级优化,如下:
1)栈上分配
2)同步消除:可以去掉同步
3)标量替换