JVM:早期(编译期)优化

xudongdong 2018-08-05

一.Javac编译器

JVM:早期(编译期)优化

1.解析与填充符号表

a.解析:parseFiles();

词法分析将源代码的字符流转化为标记(Token)集合。

语法分析根据Token序列构造抽象语法树。

b.填充符号表:enterTress();

符号表是K—V键值对的形式。

2.注解处理器

如果注解处理器在处理注解的时候对语法树进行了修改,编译器将回到解析与填充符号表过程重新处理,知道所有插入式注解处理器都没有再对语法树进行修改为止。每一次循环成为一次Round,即下图的回环:

JVM:早期(编译期)优化

3.语义分析和字节码生成

a.标注检查:attribute()

检查变量使用前是否已经被声明,变量与赋值之间的数据类型是否能够匹配。

b.数据及控制流分析:flow()

检查局部变量在使用前是否有被赋值,方法的每条路径是否都有返回值,是否所有的受查异常都被正确处理了等问题。

c.解语法糖:desugar()

泛型,可变参,自动拆装箱

4.字节码生成generate()

把前面各个步骤所声称的信息的(语法树,符号表)转化到字节码写入磁盘中,还对少量代码添加和转换。<init>()和<clinit>就是这个阶段添加到语法树之中的。

编译器会把语法块、变量初始化、调用父类的实例构造器等操作收敛到<init>()和<cliinit>()之后。且一定保证先执行父类实例构造器,然后初始化变量,最后执行语句块(对<init>()来说就是{...},对<clinit>来说就是static{...})的顺序。

二.语法糖

1.泛型和类型擦除

本质是参数化类型的应用。即:所操作的数据类型被指定为一个参数。这个参数类型可以用在类、接口、方法的创建中。

java的泛型只存在与源码之中,编译后的字节码文件,就已经替换为原来的原生类型(Raw Type,也成为裸类型),并且在相应的地方插入了强制转化代码。Java语言中泛型实现方法被称为类型擦除,是伪泛型。

擦除仅仅是对方法的Code属性中的字节码进行擦除,实际上元数据还是保留了泛型的信息,这也是我们能通过反射取得参数化类型的根本依据。

2.自动装箱拆箱与循环遍历

自动装箱拆箱在编译之后就成了对应的包装和还原方法;循环便利把代码还原成了迭代器的实现,这也是为何遍历循环需要被遍历的类实现Iterable接口。

3.条件编译

只有使用条件为常量的if语句才能达到。


  1. public static void main(String[] args) {
  2. if(true) {
  3. System.out.println("this line will be reserved");
  4. } else {
  5. System.out.println("this line will not be reserved");
  6. }
  7. }

将会变成:


  1. public static void main(String[] args) {
  2. System.out.println("this line will be reserved");
  3. }

4.还有其他的语法糖这里不做介绍

相关推荐