深入理解java虚拟机(15):编译器介绍

前端编译器,把java文件变成class文件字节码,sun的javac,Eclipse JDT中的编译插件ECJ。

JIT,just it time Hotswap的c1,c2把字节码转换成机器码,及时编译器。

AOT编译器:GCJ,JET把java文件变成机器码,静态提前编译器。

虚拟机团队把设计团队把对性能的优化集中到了后端的及时编译器,让许多不是java语言生成的class类文件也同样能享受到编译器优化带来的好处,很多新生的java语法特性是靠语法糖实现的,而不是底层虚拟机改进支持的。

1、javac编译器,java语言实现。

1)词法、语法分析,主要通过com.sun.tools.javac.parser.Scanner类实现,语法分析就是构造抽象语法树的过程,语法树的每一个节点都表示程序代码的一个程序结构,如包、类型、修饰符等。语法树由com.sun.tools.javac.tree.JCTree表示,后续操作都在语法树上操作。

2)填充符号表,符号表是一组符号地址和符号信息组成的表格,符号表将用于语义检查和产生中级代码。由com.sun.tools.javac.comp.Enter实现

2、注解处理器

注解处理器可以对语法树进行修改和添加抽象语法树上的任意元素。如果注解处理器改变了抽象语法树,编译器会回到解析和填充符号表进行处理。通过插件式注解处理器可以实现很多插件功能。java源代码中

插入式注解处理器的初始化过程是在initProcessAnnotations方法中完成,执行过程是processAnnoations中处理,这个判断是否还有新的注解处理器需要执行。如果有的话,通过com.sun.tools.javac.processing.JavaProcessingEnviroment类的doProcessing()方法生成一个新的javacompiler对象编译。

 

3、语义分析和字节码生成

语义分析主要对结构上正确的上下文有关性质的审查如下图

 

 1)标注检查

变量使用前是否被生明,变量和赋值之间的数据类型是否能够匹配等,还有常量折叠,例如int a = 1+2,编译期间进行常量折叠。负责实现标准检查的类是com.sun.tools.javac.comp.Attr类和com.sun.tools.javac.comp.Check类。

2)数据及控制流分析

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

public void foo(final int arg){

  final int val=0

}  

public void foo(final int arg){

   int val=0

}  

 从第六章的知识可以知道局部变量在常量池中没有CONSTANT_Fieldinfo的符号引用,自然没有访问标志。所以局部变量的不可改变是靠编译期间来保证的。

3)解语法糖

语法糖主要是方便编程的。java是典型的低糖语言,泛型,边长参数,自动拆箱,装箱编译阶段会还原成基础语法结构,这个过程被称为解语法糖。

4)字节码生成

将前面各个步骤,语法树和符号表转化成字节码存储在硬盘上,编译器还进行了少量的代码添加和转换工作。

一定会保证先执行父类的实例构造器,然后初始化变量,最后执行语句块的运行。

posted on 2019-11-29 17:57  清浊  阅读(612)  评论(0编辑  收藏  举报