10 早期(编译期)优化

Wu Jun 2020-01-09 20:44:20
05 Java > 01 Java 虚拟机

1 javac 编译器

javac 做了许多针对 Java 语言编码过程的优化措施来改善程序员的编码风格和提高编码效率;对性能的优化集中到了后端的即时编译器中

1.1 javac 的源码与调试

image

1.2 解析与填充符号表

解析步骤由 parseFiles 方法完成;

1)词法分析

将源代码的字符流转变为标记(Token,编译过程的最小元素,关键字、变量名、运算符等)集合,由com.sun.tools.javac.parser.Scanner类完成;

2)语法分析

是根据 Token 序列构造抽象语法树(AST,一种用来描述程序代码语法结构的树形表示方式)的过程,由com.sun.tools.javac.parser.Parser类实现,AST 由com.sun.tools.javac.tree.JCTree类表示;

3)填充符号表

由 enterTrees 方法完成;符号表是由一组符号地址和符号信息构成的表格,所登记的信息在编译的不同阶段都要用到,在语义分析中用于语义检查,在目标代码生成时用于地址分配;由com.sun.tools.javac.comp.Enter类实现;

1.3 注解处理器

1.4 语义分析与字节码生成

语义分析的主要任务是对结构上正确的源程序进行上下文有关性质的审查,主要包括

1)标注检查

变了使用前是否已被声明,变量与赋值之间的数据类型是否匹配。常量折叠。

2)数据及控制流分析

程序局部变量在使用前是否有赋值、方法的每条路径是否都有返回值、是否所有的异常都被正确处理了……

3)解语法糖

Java中最常用的语法糖主要是泛型、变长参数、自动装箱等,他们在编译阶段还原回简单的基础语法结构;在com.sun.tools.javac.comp.TransTypes类和com.sun.tools.javac.comp.Lower类中完成;

4)字节码生成

javac 编译的最后一个阶段,不仅仅是把前面各个步骤所生成的信息转化为字节码写入到磁盘中,编译器还进行了少量的代码添加和转换工作;由com.sun.tools.javac.jvm.ClassWriter类的writeClass方法输出字节码,生成最终的Class文件;

2 Java 语法糖

2.1 泛型与类型擦除

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

它们的实现比较简单,但却是 Java 语言里使用最多的语法糖;

2.3 条件编译

其它语法糖:内部类、枚举类、断言语句、对枚举和字符串的switch支持、try语句中定义和关闭资源等

3 实战:插入式注解处理器

3.1 实战目标

使用注解处理器 API 来编写一款拥有自己编码风格的校验工具

3.2 代码实现

@SupportedAnnotationTypes("*")
@SupportedSourceVersion(SourceVersion.RELEASE_6)
public class NameCheckProcessor extends AbstractProcessor {
       private NameChecker nameChecker;
       @Override
       public void init(ProcessingEnviroment processingEnv) {
             super.init(processingEnv);
             nameChecker = new NameChecker(processingEnv);
       }
       @Override
       public boolean process(Set<? extends TypeElement> annotations, RoundEnviroment roundEnv) {
             if (!roundEnv.processingOver) {
                    for (Element element : roundEnv.getRootElements()) {
                           nameChecker.checkNames(element);
                    }
             }
             return false;
       }
}