在与Java开发者交流的过程中,发现有一些开发者很难理清楚JDK、J2EE、J2EE、J2ME、JavaEE、JVM之间的关系。要理解这些,得从Javac说起。
Javac是一种编译器,能将一种语言规范转成另外一种语言规范,通常编译器都是将便于人理解的语言转化为机器容易理解的语言。Javac的任务是将Java语言先转换为JVM能够识别的一种语言,然后由JVM将JVM语言转换成当前这个机器能够识别的机器语言,即将Java源文件转换为class文件。
在讲Javac编译器有哪些工作模块和基本结构之前,我想先回忆一下编译原理的一些知识,即编译的步骤。我试着用最精简的语言去概括出那本厚厚的编译原理。
首先,读取源代码,一个字节一个字节的读出来。找出这些字节中哪些是我们定义的语法关键词如if、else、for等,要识别哪些if是合法的哪些不是,这个步骤是词法分析。词法分析的结果是从原代码中找出一些规范的Token流。
第二步,对这些Token流进行语法分析,这一步就是检查这些关键词组合在一起是不是符合Java语言规范,如if后面跟的是不是布尔表达式。语法分析的结果是形成一个符合Java语言规范的抽象语法树,这课语法树可以被我们按照新的规则再重新组织,它的作用是把语言词汇用一个结构化的形式组织在一起。
第三部,语义分析,语法分析如果成功,就把这些语法转换为更简单的语法。如Java中一些现有的函数方法转换为由if、else、for等基本关键词组成的结构,该步的结果是生成一个更接近目标语言的语法规则,形成一个注解过的抽象语法树。
最后,通过字节码生成器将注解过的抽象语法树生成字节码,其结果就是符合JVM规范的字节码。
Javac的各个模块就是为了完成上文所述任务的。因此分为四大模块:词法分析器、语法分析器、语义分析器和目标代码生成器。
词法分析器:这个过程在JavacParser的ParseCompilationUnit方法中完成的,它的源代码可以通过OpenJDK下载来查看。该方法从源文件的第一个字符开始,逐个字符的检查,按照Java语法规范依次找出package、import、类定义、以及属性和方法定义等,将这个类中的所有关键词匹配到Token类的所有项中的任何一项,即将Java源文件的字符流转变为对应的Token流,最后构建一个抽象语法树。
语法分析器:将词法分析器分析的Token流组建成更加结构化的语法树,也就是将一个个单词组装成一句话,一个完整句子。具体一点说就是按照一定的规则逐个地解析Token流中的每一项,每个语法树上的节点都是com.sun.tools.javac.tree.JCTree的一个实例。
语义分析器:在这课语法树上再进行一些处理以产生Java字节码。如给类添加默认的构造函数、检查变量在使用之前是否已经初始化、将一些常量进行合并处理、检查操作变量类型是否匹配、检查所有操作语法是否可达、检查异常是否捕获或掷出等。最后得到完善的最终的语法树。
代码生成器:遍历最终语法树生成Java字节码,这步通过com.sun.tools.javac.jvm.Gen这个类来完成。生成字节码需要进过两步:首先将Java方法中的代码块转成符合JVM语法树的命令形式,JVM的操作都是基于栈的,所有操作都必须经过出栈和进栈来完成。然后,按照JVM的文件组织格式将字节码输出到以class为扩展名的文件中。
Javac工作原理分析
最新推荐文章于 2023-02-17 08:30:00 发布