1.编译原理
java编译器在将java源码编译为一个有效的字节码文件,主要会经历4个步骤:词法解析à语法解析à语义解析à生成字节码
2.词法解析步骤
2.1词法解析过程
词法解析是javac编译器执行字节码编译的第一步。主要任务就是将java源码中的关键字和标示符等内容转换为符合java语法规范的Token序列,然后按照指定的顺序规则进行匹配校验,以便为后续的语法解析步骤做准备。
2.2 Token序列
Token无非就是一组对应源码字符集合的单词序列。简单来说,Token其实就一个枚举类型,其内部定义了许多符合java语法规范并与源码字符集合相对应的枚举常量。
2.3源码字符集合与Token之间的对应关系
问题一:源码字符集合究竟是如何转换成Token的?
答:当词法解析器需要将源码字符集合转换为Token时,就会通过Names类去调用Name类的fromChars()方法获取一个Name对象,然后在调用Keywords类的key()方法时传入这个Name对象就可以成功获取出对应Token,这样一来词法解析器即可成功地将源码字符集合转换为Token.
问题二:源码字符集合转成Token后,词法解析器是采用什么方式保存源码字符集合与Token之间的对应关系?
答:词法解析器在将源码字符转换为Token之前,会先将每一个字符集合都转换为一个对应的Name对象,也就是说,每一个源码字符集合其实就是一个Name对象,然后再由com.sun.tools.javac.parser.Keywords负责实际的Token转换任务。Keywords类会将Token中所有枚举常量全部转换为Name对象,然后将其存储在Name对象的内部类Table中,这样一来源码字符集合与Token之间对应关系就成功构成建起来了。
2.4词法解析例子——package关键字
3. 语法解析步骤
1) 语法解析指的就是将匹配后的Token序列整合为一颗结构化的抽象语法树。也就是说,词法解析后的Token序列其实还并不完善,因为这些Token所代表的只是一个对应的单个源码字符集合,还并没有按照指定的语法规则将其相关的一组或者一段Token整合起来。
2) 语法解析的主要任务恰恰就是将零散的Token按照指定的Java语法规范整合起来形成一个有机的整体,比如:一个try语句后面肯定会接上一个catch或者finally子句,这就是语法解析步骤的任务。
3) JCTree类实际上与语法树中的每一个语节点都保持着密不可分的关系,因为语法树中的每一个语法节点实际上都直接或者间接地继承了JCTree类,并且这些语法节点对象都以静态内部类的形式定义在该类中。
4.语义解析步骤
1) 为没有构造方法的类型添加缺省的无参构造方法;
2) 检查任何类型的变量在使用前是否都已经经历过初始化;
3) 检查变量类型是否与值匹配;
4) 检查STRING类型的常量进行合并处理[OW1]
5) 检查代码中所有操作语句是否可达;
6) 异常检查;
7) 解除Java语法糖。
(1).编译器在执行语义解析时,会检查String变量中是否包含多个常量信息并通过符号“+”组合在一起,如果确实存在,语义解析器则会将其合并为一个字符串,这就是常量折叠操作
(2).使用Unicode编码格式的char类型可以用于存储世界上所有的文字信息,但类型的二进制位数只有16bit,也就是说,char类型的变量只能够存储单个字符。
(3).String类型就是Java语法层面定义的一种专门用于存储字符串信息的数据结构,其底层实现无非就是替大家封装过程而已。
5.生成字节码
所谓编译字节码,无非就是将符合Java语法规范的java代码转换为符合JVM规范的字节码文件。