Java编译期优化思惟导图

编译期优化

本文参考自来自周志明《深刻理解Java虚拟机(第2版)》,拓展内容建议读者能够阅读下这本书。

文字版以下:java

编译期优化

javac的编译过程

解析和填充符号表

  • 解析 Parse数组

    • 词法分析app

      • 源代码字符流 -> 标记Token
      • 源代码字符是程序编写的最小单位,Token是编译过程的最小元素不可再分
    • 语法分析优化

      • Token序列 -> 抽象语法树AST
      • AST描述代码语法结构的树状结构,每一个节点表示一个语法结构(包、类型、修饰符、运算符、接口、返回值、注释等)
  • 填充符号表 Enterui

    • 符号表 -> 待处理列表To Do list
    • 符号表symbol table是由一组符号地址和符号信息构成的表
    • 包、类、方法、字段均可以抽象成一个符号(symbol),不一样种类的符号之间能够有包含嵌套关系,这一阶段的任务就是识别出各种符号,并对不一样种类的符号按照包含嵌套关系进行归类,并挂接到AST对应的结点上。

插入式注解处理器的注解处理

  • 使用JDK1.6后提供的插入式注解标准API来开发,这些API用于读取、修改、添加语法树的元素,运行时使用-processor参数来参与javac的编译
  • 插入式注解处理器起编译期插件做用
  • 在编译期间插入式注解处理器对注解进行处理,能够读取、修改、添加语法树的元素
  • 若是处理过程当中修改了语法树将会触发编译期回到填充符号表阶段从新处理一轮(Round),直到语法树再也不变化
  • 实例:lombok,在设置了相关注解后lombok会在编译期生成源代码中没有的方法等

分析与字节码生成

  • 语义分析spa

    • 标注检查插件

      • 变量使用前是否已经被声明
      • 变量与赋值之间的数据类型是否可以匹配
      • 常量折叠
    • 数据及控制流检查对象

      • 程序局部变量在使用前是否有赋值
      • 方法的每条路径是否都有返回值
      • 是否全部的受检异常都被正确处理
      • final参数、final局部变量是否被修改接口

        • 局部变量是否用final修饰最终在class文件中是无差异的,由于局部变量在class中是没有访问标志的,这个final不变性只在编译期检查时保证
    • 解语法糖资源

      • 泛型:编译后发生类型擦除,可是编译信息会保留Signature
      • 变长参数:编译后变成数组类型的参数
      • 自动装箱拆箱:编译后装箱经过valueOf()变成了对象,拆箱经过xxxValue()变成了原始类型值
      • 遍历循环:编译后变成了迭代器遍历
      • 条件编译:编译后将常量不可达条件分支直接消除掉
      • 内部类
      • 枚举类
      • 断言
      • switch处理枚举和字符串
      • try定义和关闭资源
  • 字节码生成

    • 处理完的语法树和符号表 -> 字节码
    • 少许的代码添加和转换工做

      • 添加<init>()和<clinit>()方法

        • <init>()收敛的操做

          • 调用父类的<init>()
          • 执行{}语句块
          • 初始化实例变量
        • <init>()是字节码级别的方法,对使用者是透明的,与每一个<init>()对应的构造方法是源码级别的方法,是真正被使用者开放的。<init>()和构造方法一一对应,是同一律念在两个级别的含义
        • <clinit>()收敛的操做

          • (JVM自动保证执行父类的<clinit>())
          • 执行static{}语句块
          • 初始化类变量
      • 字符串加操做替换为StringBuffer或StringBuilder的append()操做
相关文章
相关标签/搜索