一、编译过程
- 解析和填充符号表的过程
- 插入注解处理器的注解处理过程
- 语义分析与字节码生成过程
二、解析和填充符号表
解析包含两个过程:词法分析和语法分析
(一)词法分析
将源代码的字符流转变成标记(Token)集合,如 int aaa = bbb + 2,会被分解成6个标记,[int,aaa,=,bbb,+,2]
(二)语法分析
根据Token序列来构造抽象语法树的过程。完成解析之后,下一步是填充符号表
(三)符号表
由一组符号地址和符号信息构成的表格。
符号表登记的内容将用于语义检查和产生中间码
目标代码生成阶段,对符号名进行地址分配时,符号表是地址分配的根据
三、插入式注解处理器的注解处理过程
插入式注解处理器可以看作一组编译器的插件,在这些插件里面,可以读取、修改、添加抽象语法树中的任意元素。如果这些插件对语法树做了修改,编译器就会回到 “解析和填充符号表”过程,重新处理,直到所有插入式注解处理器都没有再对语法树进行修改为之。
四、语义分析和字节码生成过程
经过上述两个步骤之后,编译器获得了语法树,然而语法树能表示正确的源程序的抽象,但无法保证源程序是否符合逻辑,这里就需要语义分析来对 结构上正确的源程序进行上下文有关性质的检查。
int a = 1; boolean b = false; char c = 2; //构成正确的语法树,语义上没问题 int d = a + c; //构成正确的语法树,语义上不合逻辑,无法编译 int e = b + c;
(一)语义分析
分为三个部分:标注检查、数据及控制流分析、解语法糖
- 标注检查:检查变量使用前是否已声明,变量与赋值之间的数据类型是否能够匹配,常量折叠(int a = 1 + 2;折叠之后字面量为3)
- 数据及控制流分析:对程序上下文逻辑的检验,局部变量使用前是否赋值,方法的每条路径是否都有返回值,异常是否被正确处理等
- 解语法糖:将语法糖还原成基础的数据结构
(二)字节码生成
javac编译的最后一个阶段,将之前各个步骤生成的信息(语法树、符号表)转化成字节码写到磁盘中
参考
[1] 《 深入理解JVM-->程序编译与代码优化部分》 http://blog.sina.com.cn/s/blog_6c9670bb0102v78a.html
[2] 《 Java编译期优化与运行期优化技术浅析》 http://blog.csdn.net/kobejayandy/article/details/39620221
[3] 《深入理解Java虚拟机 JVM高级特性与最佳实践》 周志明