Javac的实现过程
Posted never-say-no
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Javac的实现过程相关的知识,希望对你有一定的参考价值。
主要介绍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类有三个重要属性:其实这三个属性很好理解,为了分辨出树中的每一个节点而出现的,定义了这三个属性,可以很快速的找到节点在树中的层次结构和位置。
- TreeTag:每个语法数节点都用整形常熟表示,每个节点数值都是在前一个节点的基础上执行加一操作,顶点节点TopLevel是1,那紧接着的Import节点就在TopLevel的基础上加一,等于2
- pos:整数。表示位置
- type:表示节点的类型
3、语义分析:对生成的抽象结构树进一步分析,将复杂的语法结构转换为简单的,易于理解和阅读的语法结构。例如:将增强for循环foreach转换为for循环结构。经过语义分析之后会产生一个更加具体的抽象结构树。
语义分析实现的步骤;
语义分析主要是在Enter类中完成的,这个类主要有两个步骤
(1)将所有类中出现的符号都输入到类自身的符号表中,所有的类符号,类参数列表,超类符号,和继承的接口类型符号都会存储到未处理的符号列表中(因为类除了自身的符号之后还有其他类中的引用,所以要进行分类)
(2)在未处理的符号列表中,将所有类符号解析到各自的类符号中,在MemberEnter.complete()类中完成。(解析语法树,将所有的符号都添加到符号表中)
在Enter类解析的步骤中,还有一个辅助操作:
- 添加默认的构造函数;
- 接着下一步是处理注解:在JavaProcessingEnvironment类中完成;
- 数据流分析,在Flow类中完成。
数据流分析实现的步骤:
1、检查变量在使用之前是否赋值,除了8中基本数据类型之外,还有String类型和其他对象的引用在使用之前都需要赋值。
2、使用final修饰的变量不会被重新赋值,如果重复复制会报错;同时如果变量是静态成员变量在定义的时候就必须赋值
3、分析方法返回值类型
4、所有的Checked Exception都必须向上抛出或者捕获。
5、所有的语句都会被执行,这个分析的是return语句之后是否还有语句,因为return之后的语句不会被执行。
- 语义分析器的最后一个步骤,进一步处理语法树,解决的问题
- 消除无用的代码,例如:if条件永远为false不会被执行的代码块
- 解除语法糖:说白了就是将例如增强的foreach循环转换为for循环
- 变量自动类型转换:例如:int类型和Integer类型之间相互转换
4、字节码:经过了上面的三个步骤之后,java源代码就可以被转换成为java虚拟机(JVM)能够别的字节码文件。
代码生成器:
- 将源代码转换成符合JVM语法规范的命令形式,JVM的所有操作都是基于栈操作的,因此所有的操作都在进栈和出栈中完成。
- 按照JVM文件组织的形式将字节码输出到后缀名为class的字节码文件中
整个业务流程:
关于javac的基本原理就介绍到这里,有兴趣的可以研究下Javac的源码,可以从OpenJdk下载到源码。
以上是关于Javac的实现过程的主要内容,如果未能解决你的问题,请参考以下文章