早期(编译期)优化
前端编译器(把*.java文件转变成*.class文件):Sun的Javac、 Eclipse JDT中的增量式编译器(ECJ)。
JIT编译器(把字节码转变成机器码):HotSpot VM的C1、 C2编译器。
AOT编译器(把*.java文件编译成本地机器代码):GNU Compiler for the Java(GCJ)、 Excelsior JET。
Javac编译器
编译过程大致分为三个:解析与填充符号表过程、插入式注解处理器的注解处理过程、分析与字节码生成过程。
- 解析与填充符号表过程
- 1.词法、 语法分析
- 词法分析是将源代码的字符流转变为标记(Token)集合
-
语法分析是根据Token序列构造抽象语法树的过程,抽象语法树(Abstract Syntax Tree,AST)是一种用来描述程序代码语法结构的树形表示方式,语法树的每一个节点都代表着程序代码中的一个语法结构(Construct)
图1 Javac编译过程
- 2.填充符号表
- 符号表(Symbol Table)是由一组符号地址和符号信息构成的表格
- 1.词法、 语法分析
- 注解处理器
- 如果插入式注解处理器在处理注解期间对语法树进行了修改,编译器将回到解析及填充符号表的过程重新处理,直到所有插入式注解处理器都没有再对语法树进行修改为止,如图1的回环过程(Round)。
- 语义分析与字节码生成
- 语义分析的主要任务是对结构上正确的源程序进行上下文有关性质的审查,如进行类型检查。
- 语义分析过程分为标注检查以及数据及控制流分析
- 1.标注检查
- 检查的内容包括诸如变量使用前是否已被声明、 变量与赋值之间的数据类型是否能够匹配等
- 2.数据及控制流分析
- 对程序上下文逻辑更进一步的验证,它可以检查出诸如程序局部变量在使用前是否有赋值、 方法的每条路径是否都有返回值、 是否所有的受查异常都被正确处理了等问题。
- 1.标注检查
- 局部变量与字段(实例变量、 类变量)是有区别的,它在常量池中没有
CONSTANT_Fieldref_info的符号引用,自然就没有访问标志(Access_Flags)的信息,甚至可能连名称都不会保留下来(取决于编译时的选项),自然在Class文件中不可能知道一个局部变量是不是声明为final- 3.解语法糖
- 语法糖指指在计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,但是更方便程序员使用。
- 虚拟机运行时不支持泛型、变长参数等语法,它们在编译阶段还原回简单的基础语法结构,这个过程称为解语法糖。
- 4.字节码生成
- 字节码生成阶段不仅仅是把前面各个步骤所生成的信息(语法树、 符号表)转化成字节码写到磁盘中,编译器还进行了少量的代码添加和转换工作。
- 实例构造器<init>()方法和类构造器<clinit>()方法就是在这个阶段添加到语法树之中的
- 3.解语法糖
Java语法糖
泛型与类型擦除
泛型技术实际上是Java语言的一颗语法糖,Java语言中的泛型实现方法称为类型擦除,基于这种方法实现的泛型称为伪泛型。
网友评论