第10章 早期(编译期优化) 《深入理解java虚拟机》

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/xuchuanliang11/article/details/102714663

javac编译器

编译期:1.前端编译器(javac、ECJ)把*.java文件编译成*.class文件的过程;2.后端运行期编译器(JIT编译器:C1、C2)把字节码编译成机器码的过程;3.静态提前编译器(AOT编译器:GCJ、Excelsior JET)直接把*.java编译成本地机器代码过程

javac这类编译器对代码的运行效率几乎没有优化措施,虚拟机设计团队对性能的优化集中到了后端的即时编译器中,这样可以让那些不是javac编译的class文件同样能够享受到优化带来的好处。

javac将java源程序编译成class文件经历三个过程:1.解析与填充符号表过程;2.插入式注解处理器的注解处理过程;3.分析与字节码生成过程

解析与填充符号表

解析步骤包含词法分析和语法分析

词法分析是将源代码的字符流转变为标记(Token)集合,单个字符是程序编写过程的最小元素,而单个标记是编译过程的最小元素,关键字、变量名、字面量、运算符都可以成为标记;

语法分析是根据Token序列构造抽象语法树的过程,抽象语法树是一种用来描述程序代码结构的树形表示方式,语法树中的每个节点都代表着程序代码中的一个语法结构

填充符号表

符号表是一种由符号地址和符号信息构成的表格,类似于哈希表中的K-V键值对形式。符号表中所登记的信息在编译的不同阶段都要用到。在语义分析中,符号表所登记的内容将用于语义检查和产生中间代码。在目标代码生成阶段,当对符号名进行地址分配时,符号表是地址分配的依据。

分析与字节码生成

语义分析:对结构上正确的源程序进行上下文性质的审查。主要包括标注检查和数据及控整流分析两个步骤。

标注检查步骤检查的内容包括变量使用前是否声明、变量与赋值之间的数据类型是否匹配等。

数据及控制流分析是对程序上下文逻辑更进一步验证,它可以检查出诸如程序局部变量在使用前是否有赋值、方法的每条路径上是否有返回值、是否所有的受检查异常都被正确的处理了等。

解语法糖

语法糖:在计算机语言中添加某种语法,这种语法对语言功能没有影响,方便程序员使用。

解语法糖:java虚拟机运行时不支持的语法,如泛型、变长参数、自动装箱/拆箱等在编译阶段还原回简单的语法结构分析。

字节码生成

实例构造器<init>()和类构造器<clinit>()就是在这个阶段添加到语法树中,两个构造器的产生是一个代码收敛的过程,编译器会把语句块(对于实例构造器而言是{},对于类构造器而言是static{})、变量初始化(实例变量和类变量)、调用父类的实例构造器等操作收敛到<init>()和<clinit>()方法之中,并且保证一定是按先执行父类的实力构造器、然后初始化变量、最后执行语句块的顺序。

java语法糖的味道

泛型与类型擦除

java语言中的泛型只在源码中存在,编译成字节码文件后,就已经被替换成原生类型,并且在相应的地方插入了强制转型代码。因此java的泛型实际上是伪泛型。

上图中我们可以看到编译后的文件再反编译发生了一些变化,泛型也消失了,并且增加了强转。这也就限制了我们在重载方法时,如果只是泛型不同,则会编译不通过,如图所示:

自动装箱、拆箱和遍历循环

图中我们可以看到编译前后java编译器对我们代码的优化

猜你喜欢

转载自blog.csdn.net/xuchuanliang11/article/details/102714663
今日推荐