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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 如何查找网上的资源

    如何查找网上的资源一:电驴近期添加了版权                                                http://www.verycd.com/绕过验证的方法是 在verycd网址的”verycd.”与”com”之间,加上“gdajie.”,回车ed2k:

    2022年7月15日
    19
  • Linux系统调用Hook姿势总结

    Linux系统调用Hook姿势总结http://www.cnblogs.com/LittleHann/p/3854977.html主题Linux相关学习资料http://xiaonieblog.com/?post=121http://hbprotoss.github.io/posts/li-yong-ld_preloadjin-xing-hook.htmlhttp://www.catonma

    2022年5月9日
    225
  • 二叉树的五个性质「建议收藏」

    二叉树的五个性质「建议收藏」性质1:在二叉树的第i层上最多有2^(i-1)个结点(i≥1)。第一层是根结点,只有一个,所以2(1-1)=20=1。第二层有两个,2(2-1)=21=2。第三层有四个,2(3-1)=22=4。第四层有八个,2(4-1)=2^3=8。性质2:深度为k的二叉树至多有2^k-1个结点(k≥1)。注意这里一定要看清楚,是2k后再减去1,而不是2(k-1)。以前很多同学不能完全理解,这样去记忆,就容易把性质2与性质1给弄混淆了。深度为k意思就是有k层的二叉树,我们先来看看简单的。如果有一层,至多1=

    2022年5月31日
    40
  • ipfs矿机挖币是骗局(ipfs挖矿用什么网络)

    友情提示:Filecoin还没上线,任何打着Filecoin旗号说现在就能挖矿的都是骗纸!币圈人对挖矿这件事情上心还得要扯到比特币。2012年的时候,阿瓦隆的创始人开发了ASIC芯片,当时ASIC矿机一面世,平均一天可以挖到375枚比特币!你没有看错是375枚!按照当时的比特币价格计算,阿瓦隆一天的挖矿收入就是20万元型态人民币!赚的盆满钵满! 时光一去不复返,如今的比特币挖矿行业竞争已经进入白…

    2022年4月14日
    50
  • Apache Struts2打开重定向/命令执行 CVE-2013-2251「建议收藏」

    Apache Struts2打开重定向/命令执行 CVE-2013-2251「建议收藏」昨日,著名JavaWeb框架Struts官方再发高危安全漏洞补丁升级(最新版本为:2.3.15.1),升级修补了多个安全漏洞,其中包括一个远程任意代码的高危安全漏洞,这些漏洞可以影响到Struts2.0.0-Struts2.3.15的所有版本。攻击者可以利用该漏洞,执行恶意Java代码,最终导致网站数据被窃取、网页被篡改等严重后果。基于Struts2使用广泛,目前很多网站还没有升级,另外

    2022年7月13日
    14
  • 数据库concat函数

    数据库concat函数因文件改动读到老大写的代码发现该函数所以记录一下concat用法就是将数据库不同的字段串起来比如要查询nameagesex最终想出来的结果是连起来的就可以用该函数而不用再将结果拼接eg:selectid,concat(name,sex,age)asinfofromusr;这样就会输出结果info=>小明男12该函数中间可以拼接字符用来分割eg:selectid,concat(name,”,sex,”,age)…

    2022年5月9日
    71

发表回复

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

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