Java代码编译过程简述
代码编译是由Javac编译器来完成,流程如下图1所示:
Javac是一种编译器,能将一种语言规范转化成另外一种语言规范,通常编译器都是将便于人理解的语言规范转化成机器容易理解的语言规范,如C/C++或者汇编语言都是将源代码直接编译成目标机器码,这个目标机器代码是CPU直接执行的指令集合。这些指令集合也就是底层的一种语言规范。
Javac的编译器也是将Java这种对人非常友好的编程语言编译成对对所有机器都非常友好的一种语言。这种语言不是针对某种机器或某个平台。怎么消除不同种类,不同平台之间的差异这个任务就有JVM来完成,而Javac的任务就是将Java源代码语言转化为JVM能够识别的一种语言,然后由JVM将JVM语言再转化成当前这个机器能够识别的机器语言。
Javac的任务就是将Java源代码编译成Java字节码,也就是JVM能够识别的二进制代码,从表面看是将.java文件转化为.class文件。而实际上是将Java源代码转化成一连串二进制数字,这些二进制数字是有格式的,只有JVM能够真确的识别他们到底代表什么意思。
编译器把一种语言规范转化为另一种语言规范的这个过程需要哪些步骤?回答这个问题需要参照《编译原理》,总结过程如下:
1)词法分析:一个字节一个字节的读取源码并生成token流,同时在此过程中判断关键字的使用是否合法
词法分析的结果:生成规范化的token流。
2)语法分析:对词法分析中得到的token流进行语法分析,检查语句是否符合Java语言规范。如if的后面是不是紧跟着一个布尔型判断表达式。
语法分析的结果:形成一个符合Java语言规定的抽象语法树(结构化的语法表达形式)。
3)语义分析:把复杂语法转化成简单语法将foreach转化为for循环、添加缺少的内容如默认构造函数、检查遍变量是否初始化以及变量操作类型是否匹配。
语义分析结果:生成一棵抽象的更接近目标语言的语法规则的语法树。
4)字节码生成:遍历上述生成的抽象语法树生成符合java虚拟机规范的字节码。
在上述过程中涉及到的组件以及字节码生成过程如下图所示:
从上面的描述中我们知道编译就是将一种语言通过分析分解,再按照一定的方式先形成一个简单的框架(将Java源文件的字节流转化为对应的token流)然后在通过详细的分析按照一定的规定在这个框架里添加东西使这个token流形成更加结构化的语法树(就是将前面生成的token流中的一个个单词组装成一句话),但是这棵树离我们的目标—Java字节码还有点差距,所以再进行语义分析使那颗粗糙的树更加完整完善(给类添加默认的构造函数,检查变量在使用前有没有初始化,检查操作变量类型是否匹配),然后javac编译器调用com.sun.tools.javac.jvm.Gen类遍历这棵语法树将java方法中的代码块转换成符合JVM语法的命令形式的二进制数据。按照JVM的文件组织格式将字节码输出到以class为扩展名的文件中,也就是生成最终的java字节码。词法分析就是将关键词组织成token流即检查源码中的的关键词是否正确并组织成token流,而语法分析就是检查源码是否符合java语法规范并将词组成语句。语义分析就是简化复杂的添加缺少的,检查变量类型是否合法。代码生成器就是遍历这棵树生成符合JVM规范的代码。
转载:https://blog.csdn.net/fuzhongmin05/article/details/54880257。