美文网首页
早期(编译期)优化

早期(编译期)优化

作者: 官子寒 | 来源:发表于2020-02-24 09:44 被阅读0次
Javac的编译过程

1. 解析与填充符号表

1.1 词法、语法分析

  • 词法分析:将源代码的字符流变成Token的过程
    例如:int a = b + 1包含6个Token
  • 语法分析:根据Token序列生成抽象语法树的过程
    • 经过这个步骤之后,编译器就不会对源码文件进行操作,而是直接操作于抽象语法树

1.2 填充符号表

符号表:由一组符号地址符号信息构成的表格,表中的信息在不同的阶段都需要用到。例如在语义分析中要用做语义检查产生中间代码;在目标代码生成阶段,当对符号名进行地址分配时,符号表是地址分配的依据

2. 注解处理器

注解处理器:Java 1.6 提供了一系列插件,可以看作是一组编译器插件,在里面可以读取、修改、添加抽象语法树的任意元素。如果在这个过程中进行了任何修改,则编译器会回到解析与填充符号表阶段重新处理,直到所有的插入式注解处理器都没有再对抽象语法树进行修改为止

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

语义分析:对结构正确的源程序进行上下文有关性质的审查,如进行类型审查

3.1 标注检查

标注检查:包括检查变量使用前是否被声明过,变量与赋值数之间的类型是否匹配等,其中有一个很重要的动作成为常量折叠

  • 常量折叠:int a = 1 + 2 在语法树上仍能看到 1 和 2, 但经过常量折叠后直接被折叠成字面量3

3.2 数据及控制流分析

数据及控制流分析:检查程序局部变量是否有赋值,方法的每条路径是否有返回值,所有的异常是否正确处理等问题。

类加载时期数据及控制流分析的区别:有一些校验项只能在编译时期进行

private void foo(final int arg) {
 final int a = 1;
  // do something
}

private void foo(int arg) {
  int a = 1;
  // do something
}

这两个方法生成的Class文件一样,因为局部变量没有CONSTANT_Field_Info修饰符,自然没有访问标志信息,自然在Class文件中不可能知道一个局部变量是否被声明为final

3.3 解语法糖

语法糖:对语言的功能并没有影响,但是方便程序员使用的语法

3.4 字节码生成

  • 不仅把前面各个阶段所生成的信息加载转化成字节码写入磁盘中,还进行了少量的代码添加工作
    • 例如构造器和类构造器<init>()<cinit>()方法就是在这个阶段被加载的

4. Java语法糖的味道

4.1 泛型与类型擦除

  • 在Java中,泛型在字节码文件中就会被替换成原来的原生类型,并且在相应的地方插入了强制转型代码,因此ArrayList<int>ArrayList<int>是同一个类

4.2 自动装箱、拆箱和遍历循环

Java自动装箱的陷阱

4.3 条件编译

条件编译:也是Java里的一颗语法糖,根据布尔常量值的真假,编译器会把分支中不成立的代码块消除掉

相关文章

网友评论

      本文标题:早期(编译期)优化

      本文链接:https://www.haomeiwen.com/subject/marpfhtx.html