class类文件
- class文件是一组以8位字节为基础单位的二进制流
- class文件格式采用一种类似C语言结构体的伪结构来存储数据, 只有两种数据结构:
- 无符号数
- 表—-习惯性以”_info”结尾
- 限制格式
- 大端(高位在前)
- 哪个字节表示什么含义,长度多少,先后顺序
class 类文件格式
如图下
- 无分隔符
- 由集合组成【集合 = 前置容量计数器 + 若干连续的数据项】
- 数据存储的字节序为:大端 Big-Endian
常量池
主要放置:
字面量(Literal)
- 文本字符串
- 声明为final的常量值等
符号引用(Symbolic References)
- 类和接口的全限定名(Fully Qualified Name)
- 字段的名称和描述符(Descriptor)
- 方法的名称和描述符
早期编译
javac大致分为三个过程
com.sun.tools.javac.main.JavaCompiler
- 解析和填充符号表过程-Parse and Enter
- 词法分析,语法分析—parseFiles
- 输入到符号表—enterTree
- 插入式注解处理器的处理过程-Annotation Processing
- 执行注解处理—processAnnotations
- 语义分析与字节码生成过程-Analyse and Generate
- 标注—attribute
- 数据流分析解语法糖—desugar
- 生成字节码—generate
词法分析, lexical analysis or scanning
com.sun.tools.javac.parser.Scanner
语法分析, syntax analysis or parsing
com.sun.tools.javac.parser.Parser
根据Token序列构造抽象语法树的过程
填充符号表
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)
- storage allocated for a name
语义分析, semantic analysis
标注检查(attribute)
- 变量使用前是否已经被声明、
- 变量和赋值之间的类型是否匹配
- 常量折叠
数据及控制流分析
对上下文逻辑更进一步验证
- 局部变量在使用前是否有赋值
- 方法的每条路径是否都有返回值
- 是否所有的受查异常被正确处理等
解语法糖
- 泛型
- val, var , companion
字节码生成
- 把语法树、符号表转化成字节码写到磁盘
- 少量代码添加和转换(如字符串+ 转为stringbuffer/stringbuilder)
kotlin编译过程
Kotlin编译器在目标代码生成环节做了很多类似于Java封装的事情,比如自动生成Getter/Setter代码的生成、Companion转变成静态类、修改类属性为final不可继承等等工作。可以说,大部分Kotlin的特性都在这个环节处理产生。可以这么说,Kotlin将我们本来在代码层做的一些封装工作转移到了编译后端阶段,以使得我们可以更加简洁的使用Kotlin语言。