class类文件

  • class文件是一组以8位字节为基础单位的二进制流
  • class文件格式采用一种类似C语言结构体的伪结构来存储数据, 只有两种数据结构:
    • 无符号数
    • 表—-习惯性以”_info”结尾
  • 限制格式
    • 大端(高位在前)
    • 哪个字节表示什么含义,长度多少,先后顺序

class 类文件格式

如图下

  • 无分隔符
  • 由集合组成【集合 = 前置容量计数器 + 若干连续的数据项】
  • 数据存储的字节序为:大端 Big-Endian

class_type.png

魔数、版本号、常量池、

常量池

主要放置:

  • 字面量(Literal)

    • 文本字符串
    • 声明为final的常量值等
  • 符号引用(Symbolic References)

    • 类和接口的全限定名(Fully Qualified Name)
    • 字段的名称和描述符(Descriptor)
    • 方法的名称和描述符

早期编译

javac大致分为三个过程

  1. com.sun.tools.javac.main.JavaCompiler
  • 解析和填充符号表过程-Parse and Enter
    • 词法分析,语法分析—parseFiles
    • 输入到符号表—enterTree
  • 插入式注解处理器的处理过程-Annotation Processing
    • 执行注解处理—processAnnotations
  • 语义分析与字节码生成过程-Analyse and Generate
    • 标注—attribute
    • 数据流分析解语法糖—desugar
    • 生成字节码—generate

javacompile1.png

javacompile2.png

词法分析, lexical analysis or scanning

  1. com.sun.tools.javac.parser.Scanner

将源代码的字符流转变为标记集合(Token)

语法分析, syntax analysis or parsing

  1. com.sun.tools.javac.parser.Parser

根据Token序列构造抽象语法树的过程

填充符号表

  1. com.sun.tools.javac.comp.Enter
  • 符号表是由一组符号地址和符号信息构成的表格(Symbol Table)
  • 符号表登记的内容用于语义检查和产生中间代码
    • 语义检查:譬如检查一个名字的使用和原先的说明是否一致
    • 目标代码生成阶段:对符号名进行地址分配时,符号表是地址分配的依据
  • symbol table
    • storage allocated for a name
      • its type
      • its scope
    • procedure names
      • the numbers and types of its arguments
      • the method of passing each arguments(by value or by reference)

语义分析, semantic analysis

标注检查(attribute)

  • 变量使用前是否已经被声明、
  • 变量和赋值之间的类型是否匹配
  • 常量折叠

数据及控制流分析

对上下文逻辑更进一步验证

  • 局部变量在使用前是否有赋值
  • 方法的每条路径是否都有返回值
  • 是否所有的受查异常被正确处理等

解语法糖

  • 泛型
  • val, var , companion

字节码生成

  • 把语法树、符号表转化成字节码写到磁盘
  • 少量代码添加和转换(如字符串+ 转为stringbuffer/stringbuilder)

kotlin编译过程

Kotlin编译器在目标代码生成环节做了很多类似于Java封装的事情,比如自动生成Getter/Setter代码的生成、Companion转变成静态类、修改类属性为final不可继承等等工作。可以说,大部分Kotlin的特性都在这个环节处理产生。可以这么说,Kotlin将我们本来在代码层做的一些封装工作转移到了编译后端阶段,以使得我们可以更加简洁的使用Kotlin语言。