Javac编译过程「建议收藏」

Javac编译过程「建议收藏」Javac编译过程大致分为4个过程,分别是:词法分析语法分析语义分析代码生成词法分析  词法分析是将源代码的字符流转变为标记(Token)集合,单个字符是程序编写过程的最小元素,而标记则是编译过程的最小元素,关键字、变量名、字面量、运算符都可以成为编辑,如“inta+b=2”这句代码中包含了6个标记,分别是int、a、=、b、+、2,虽然关键字int由三个字符构成,但是

大家好,又见面了,我是你们的朋友全栈君。


欢迎支持笔者新作:《深入理解Kafka:核心设计与实践原理》和《RabbitMQ实战指南》,同时欢迎关注笔者的微信公众号:朱小厮的博客。
Javac编译过程「建议收藏」


欢迎跳转到本文的原文链接:https://honeypps.com/java/javac-compile-process/

  Javac编译过程大致分为4个过程,分别是:

  1. 词法分析
  2. 语法分析
  3. 语义分析
  4. 代码生成

##词法分析
  词法分析是将源代码的字符流转变为标记(Token)集合,单个字符是程序编写过程的最小元素,而标记则是编译过程的最小元素,关键字、变量名、字面量、运算符都可以成为编辑,如“int a+b=2”这句代码中包含了6个标记,分别是int、a、=、b、+、2,虽然关键字int由三个字符构成,但是它只是一个Token,不可再拆分。在Javac的源码中,词法分析过程由com.sun.tools.javac.parser.Scanner类来实现。


##语法分析

  词法分析器的作用是将Java源文件的字符流转变成对应的Token流。而语法分析器是将词法分析器分的Token流组件成更加结构化的语法树,也就是将一个个单词组装成一句话,一个完整的语句。哪些词语组合在一起是主语,哪些是谓语、哪些是宾语、哪些是定语等没要做进一步区分。
  语法分析是根据Token序列构造抽象语法树的过程,抽象语法树是一种用来描述程序代码语法结构的树形表示方式,语法树的每一个节点都代表着程序代码中的一个语法结构,例如包、类型、修饰符、运算符、接口、返回值甚至代码注释等都可以是一个语法结构。语法分析过程由com.sun.tools.javac.parser.Parser类实现,这个阶段产出的抽象语法树由com.sun.tools.javc.tree.JCTree类表示,经过这个步骤之后,编译器就基本不会再对源码文件进行操作了,后续的操作都是建立在抽象语法树上。


##语义分析
  语法分析之后,编译器获得了程序代码的抽象语法树表示,语法树能表示一个结构正确的源程序的抽象,但无法保证源程序是符合逻辑的。语义分析是要在语法树的基础上再做一些处理,如给类添加默认的构造函数,检查变量在使用前是否已经初始化,将一些常量进行合并处理,检查操作变量类型是否匹配,检查所有的操作语句是否可达,检查checked exception是否正确处理。
  语义分析阶段分为:填充符号表、标注检查、数据及控制流分析。

填充符号表
  符号表是由一组符号地址和符号信息构成的表格,读者可以把它想象成哈希表K-V值对的形式。符号表中所登记的信息在编译的不同阶段都要用到。在语义分析中,符号表所登记的内容将用于语义检测和产生中间代码。在目标代码生成阶段,当对符号名进行地址分配时,符号表是地址分配的依据。在Javac源码中,填充符号表的过程由com.sun.tools.javac.comp.Enter类实现。
  一个类除了类本身会定义一些符号变量如类名称、变量名称和方法名称等,还有一些符号是引用其它类的,这些符号会调用其它类的方法或者变量等,还有一些类可能会继承或者实现超类和接口等。这些符号都是在其他类中定义的,那么就需要将这些类的符号也解析到符号表中。
  在Enter类解析这一步骤中,还有一个重要的步骤就是添加默认的构造函数。如果代码中没有提供任何构造函数,那么编译器将会添加一个没有参数、访问下与当前一致的默认构造函数。

标注检查
  检查的内容包括诸如变量的类型是否匹配、变量在使用前是否已经初始化、能够推导出泛型方法的参数类型、字符串常量的合并(常量折叠)。在标注检查步骤中一个重要的动作称为常量折叠,如果我们在代码中写了如下定义:

int a=1+2;

  那么在语法树上仍然能看到字面量1、2以及操作符+,但是在进过常量折叠之后,他们将会被折叠为字面量3.实现的类是com.sun.tools.javac.comp.Attr类和com.sun.tools.javac.comp.Check类。

数据流分析
  数据流主要完成如下工作:

  • 检查变量在使用前是否都已经被正确赋值。
  • 保证final修饰的变量不会被重复赋值。
  • 要确定方法的返回值类型。这里需要检查方法的返回值类型是否确定,并检查接受这个方法返回值的引用类型是否匹配,如果没有返回值,则不能有任何引用类型指向方法的这个返回值。
  • 所有的Checked Exception都要捕获或者向上抛出。
  • 所有的语句都要被执行到。这里会检查是否有语句出现在一个return方法的后面,因为在return方法后面的语句永远也不会被执行到。

控制流分析
  控制流主要完成如下工作:

  • 去掉无用的代码,比如永假的if代码块。
  • 变量的自动转换,比如自动装箱拆箱。
  • 去除语法糖。解语法糖的过程由desugar()方法触发,在com.sun.tools.javac.comp.TransTypes和com.sun.tools.javac.comp.Lower类中完成。
    数据流及控制流的分析入口是flow()方法,具体操作由com.sun.tools.javac.comp.Flow类来完成。

##字节码生成
  由com.sun.tools.javac.jvm.Gen类来完成。字节码阶段不仅仅把前面各个步骤所生成的信息(语法树、符号表)转化成字节码写到磁盘中,编译器还进行了少量的代码添加和转换工作。
实例构造器<init>方法和类构造器<clinit>方法就是在这个阶段添加到语法树中的。
  生成java字节码需要经过以下两个步骤:

  • 将java方法中的代码块转化成符合JVM语法的命令形式,JVM的操作都是基于栈的,所有的操作都必须经过出栈和进栈来完成。
  • 按照JVM的文件组织格式将字节码输出到以class为扩展名的文件中。

  在jdk1.5之后,java语言提供了对注解(Annotation)的支持,这些注解与普通的Java代码一样,是在运行期间发挥作用的。在Jdk1.6中提供了一组插入式注解处理器的标准API在编译期间对注解进行处理,我们可以把它看做是一组编译器的插件,在这些插件里面,可以读取、修改、添加抽象语法树中的任意元素。如果这些插件在处理注解期间对语法树进行了修改,编译器将回到解析及填充符号表的过程重新处理,直到所有插入式注解处理器都没有再对语法树进行修改为止。对注解的处理是在填充符号表之后及在标注注解之前发生的。


##参考

  1. 《深入理解Java虚拟机》周志明著。
  2. 《深入分析Java Web技术内幕》许令波著。

欢迎跳转到本文的原文链接:https://honeypps.com/java/javac-compile-process/

欢迎支持笔者新作:《深入理解Kafka:核心设计与实践原理》和《RabbitMQ实战指南》,同时欢迎关注笔者的微信公众号:朱小厮的博客。
Javac编译过程「建议收藏」


版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/140475.html原文链接:https://javaforall.net

赞 (0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • HTML表格代码_html如何制作表格代码

    HTML表格代码_html如何制作表格代码表格代码<table></tabie><tablewidth(表格宽度。可以用像素或百分比表示。)=””height=””(行高)border=””(边框)cellpadding=””(内容跟单元格边框的边距。)cellspacing=””(单元格之间的间距。)align=””(对齐方式。)bgcolor=””(背景色)background=””(背景图片。)><tr(行)align=””(一行的内容的水平对齐方式)valign(一行的内容的垂平对齐.

    2022年8月11日
  • touchstart,touchmove,touchend触摸事件的小小实践心得

    近段时间使用html5开发一个公司内部应用,而触摸事件必然是移动应用中所必须的,刚开始以为移动设备上或许也会支持鼠标事件,原来是不支持的,好在webkit内核的移动浏览器支持touch事件,并且打包成

    2021年12月27日
  • 解决idea的控制台输出Tomcat日志乱码问题「建议收藏」

    解决idea的控制台输出Tomcat日志乱码问题「建议收藏」解决idea的控制台输出Tomcat日志乱码问题乱码原因由于window下的idea默认编码集都默认是GBK,而Tomcat目前版本是UTF-8,所以会出现乱码。第一种解决方案:将Tomcat输出日志的编码改为GBK在Tomcat的config目录下有一个logging.properties文件,文件中可以在五个地方设置编码,分别对应红色圆圈内五个日志输出文档(默认只选中了两个),将UTF-8的地方全改成GBK1catalina.org.apache.juli.FileHandler.l

    2022年9月25日
  • 机器学习之数据预处理

    在sklearn之数据分析中总结了数据分析常用方法,接下来对数据预处理进行总结当我们拿到数据集后一般需要进行以下步骤:(1)明确有数据集有多少特征,哪些是连续的,哪些是类别的(2)检查有没有缺失

    2021年12月30日
  • 如何求最长回文子串

    如何求最长回文子串回文字符串,就是像“12321”这种轴对称形式的字符串,系不系很简单呀(狗头)。但并不是所有的字符串都是这种整个串都是回文串的。有些计算机问题就是在一个字符串中找出一段最长的回文字符子串,这个时候时候,我们会很自然的想到一种暴力的方法来解决。1975年,一位叫Manacher的人发明了一个算法,这个算法是用来查找一个字符串的最长回文子串的方法。…

    2022年5月8日
  • 《Python程序设计与算法基础教程(第二版)》江红 余青松 全部章节的课后习题,上机实践,课后答案,案例研究「建议收藏」

    《Python程序设计与算法基础教程(第二版)》江红 余青松 全部章节的课后习题,上机实践,课后答案,案例研究「建议收藏」1.这本书对Python的知识点的描述很详细,而且排版看的很舒服.2.几个例题:假装自己从零开始学,将一些有代表性、有意思的例题抽取出来.3.还有自己对一部分课后复习题,全部课后上机实践题的解题思路

    2022年8月26日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号