主要介绍Javac的实现过程及原理。
首先弄明白什么是Javac?
Javac是一种编译器,将一种语言转换为另一种语言规范。编译器的作用就是将符合java语言规范的源代码转化为JVM虚拟机能够识别的字节码文件的过程。
对于java而言。javac任务就是将java源代码转换为jvm能够识别的二进制码。将.java文件转换为.class文件,这些.class文件也就是字节码文件只有JVM能够识别。
编译过程的原理:
1、词法分析:首先将源代码按照字节的方式读取,然后找出定义的语法关键字(if/else/for等),然后判断哪些关键字是符合java语言规范的,经过整理分析返回一些规范化的Token流
2、语法分析:对Token流进行分析。分析出这些关键字组合在一起是否符合java语言规范,经过分析之后会产生一个符合java规范的抽象语法树。抽象语法树就是一个结构化的语法表达式,作用就是将词法用一个结构化的形式组合在一起。
Java的语法树使java源码更加结构化,每个语法树上的节点都是一个JCTree实例
JCTree类有三个重要属性:其实这三个属性很好理解,为了分辨出树中的每一个节点而出现的,定义了这三个属性,可以很快速的找到节点在树中的层次结构和位置。
3、语义分析:对生成的抽象结构树进一步分析,将复杂的语法结构转换为简单的,易于理解和阅读的语法结构。例如:将增强for循环foreach转换为for循环结构。经过语义分析之后会产生一个更加具体的抽象结构树。
语义分析实现的步骤;
语义分析主要是在Enter类中完成的,这个类主要有两个步骤
(1)将所有类中出现的符号都输入到类自身的符号表中,所有的类符号,类参数列表,超类符号,和继承的接口类型符号都会存储到未处理的符号列表中(因为类除了自身的符号之后还有其他类中的引用,所以要进行分类)
(2)在未处理的符号列表中,将所有类符号解析到各自的类符号中,在MemberEnter.complete()类中完成。(解析语法树,将所有的符号都添加到符号表中)
在Enter类解析的步骤中,还有一个辅助操作:
数据流分析实现的步骤:
1、检查变量在使用之前是否赋值,除了8中基本数据类型之外,还有String类型和其他对象的引用在使用之前都需要赋值。
2、使用final修饰的变量不会被重新赋值,如果重复复制会报错;同时如果变量是静态成员变量在定义的时候就必须赋值
3、分析方法返回值类型
4、所有的Checked Exception都必须向上抛出或者捕获。
5、所有的语句都会被执行,这个分析的是return语句之后是否还有语句,因为return之后的语句不会被执行。
4、字节码:经过了上面的三个步骤之后,java源代码就可以被转换成为java虚拟机(JVM)能够别的字节码文件。
代码生成器:
整个业务流程:
关于javac的基本原理就介绍到这里,有兴趣的可以研究下Javac的源码,可以从OpenJdk下载到源码。