早期编译优化

分析了 java 源代码编译为字节码的过程。

分析 java 中泛型,主动装箱拆箱,条件编译等多种语法糖的前因后果。

一、Javac 编译器

javac 的编译分为三个过程:

1、解析与填充符号表

  • 词法分析是将源代码的字符流转变为标记集合。

  • 语法分析是根据 Token 序列构造抽象语法树的过程。后续操作都是建立在语法树基础之上。

  • 符号表是由一组符号地址和符号信息构成的表格。在语义分析中用于语义检查和生成中间代码,在目标代码生成阶段,依据符号表对符号名进行地址分配。

2、注解处理器

插入式注解处理器可以在编译期间对注解进行处理,可以修改语法树,然后编译器将回到第一步重新处理。

语法树中任意元素都可以在插件之中访问到。

3、语义分析与字节码生成

词法语法分析生成的抽象语法树,不能保证源程序是符合逻辑的。所以需要语义分析来进行检查。

语义分析分为标注检查以及 数据及控制流分析两个步骤。

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

2)数据及控制流分析:对程序上下文逻辑的进一步验证。

3)语法糖:泛型,变长参数,自动装箱拆箱

4)字节码生成:将前面各个步骤的信息转换成字节码写入到磁盘中,还进行少量代码添加和转换工作。

  • 将实例构造器和方法构造器添加到语法树之中
  • 将字符串的+操作替换为 stringBuffer 或 StringBuilder
  • 完成了对语法树的遍历和调整,会把填充了所有信息的符号表交给 ClassWriter,生成 class 文件

二、Java 语法糖

1、泛型与类型自动擦除

  • C# 的泛型是在系统运行期生成的,有自己的虚方法表和类型数据,这种实现称为类型膨胀,真实泛型
  • Java 的泛型只在程序源码中存在,在字节码中已经擦除了,属于伪泛型

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

3、条件编译

通过条件为常量的 if 语句来实现

条件编译是指源程序的代码行,可以在满足一定条件的情况下才进行编译,而未选中的源码,不会生成中间码或机器码,即部分内容参与编译。

条件编译的好处:对于不同硬件平台或者软件平台,或者不同功能模块的代码,编写到在同一个源文件,从而方便程序的维护和移植。