深入理解Java虚拟机----(九)程序编译和代码优化

本文深入探讨Java虚拟机的程序编译过程,包括解析与填充符号表、插入式注解处理器、泛型类型擦除。同时,讲解了Java的编译层次,从解释执行到C1和C2编译器的优化策略。此外,文章还讨论了热点代码检测方法、方法调用计数器、回边计数器以及各种优化技术,如公共子表达式消除、数组边界检查消除、方法内联和逃逸分析等。
摘要由CSDN通过智能技术生成
早期优化
     javac 把.java文件编译为class文件的这个编译过程,几乎没做什么优化,几乎将优化都放到了后端的即时编译器中,这样是为了其他非javac编译的程序也能享受到优化的待遇。但javac给我们提供了很多便于编程的语法糖,大大的方便了我们。可以说后端优化提高了运行效率,前端优化对于编码更加密切。
    javac编译过程可大致分3步:
  • 解析与填充符号表
  • 插入式注解处理器的注解处理
  • 分析与字节码生成:语义分析,保证代码符合逻辑。解语法糖是在这一步。
    
     语法糖
  • 泛型、类型擦除:本质是参数化类型的应用,也就是操作的数据类型被指定为一个参数。可以应用到类、接口、方法上。泛型其实是javac提供给我们的一颗语法糖,因为它在编译阶段采用类型擦除,将泛型还原为裸类型。r然后在适当的位置加入类型转换操作。例如:ArrayList<String> list在编译后,我们再反编译class文件,可以看到代码变成了ArrayList list。这是一种伪泛型。在c#中,List<int>和List<String>是完全不同的两个类型,是真实泛型,而在java中由于类型擦除,他们是相同的类型。所以,一个类中如果声明了两个方法void fun(List<Integer>) 和 void fun(List<String>)是不能通过编译的,很显然,他们被类型擦出后,变成了相同参数类型。如果改成void fun(List<Integer>) 和 int fun(List<Integer>),就可以编译过了(JDK1.6以后)!返回值类型不是不参与重载么?价值观被颠覆了?其实返回值类型并没有参与重载,但是在Class文件格式中,只要描述符不是完全相同的方法就可以共存。后来为了获取参数化类型,虚拟机规范做了修改(JDK1.5),引入了Signature等解决泛型带来的参数类型识别问题。Signature就保存了参数化类型的信息。
  • 自动拆装箱、遍历循环:
public static void main(String[] args) {
  
List<Integer> list = Arrays.asList(1,2,3,4);
int sum = 0;
for(int i : list) {
sum += i;
}
System.out.println(sum);
}
        这段代码用到了5各语法糖:可变长参数、拆箱、装箱、遍历循环、泛型。我们看一下,编译后再反编译的代码:
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值