java程序从javac编译过程到运行的过程是怎样的

  javac编译过程其本质是将一种语訁规范转换成另一种语言规范即将Java语言规范转换为JVM虚拟机语言规范。结果就是.java文件到.class文件

对于C/C++javac编译过程直接将高级语言转换为机器语訁,Java语言不是采用这种策略而是将高级语言javac编译过程成一种中间态的语言--与平台无关,其执行

过程是依靠对应平台的JVM在执行时刻逐条的將字节码指令转换为对应的机器语言为了提高转换速度存在JIT技术。

二、javacjavac编译过程的具体过程

  词法分析:扫描源程序的字符流按照源程序语言的的词法规则选取各类单词符号,产生用于语法分析的记号序列同时创建符号表,将

所有的标识符记录在符号表中

  语法分析:是javac编译过程过程的核心,依据源程序的语法规则组织上一步产生的记号序列。形成一个按照特定语法规则组织的结构---通常是语法

  语义分析:主要包括两部分的内容语义检查,其就是对上步产生的语法树进行检查包含类型检查、控制流检查、唯一性检查等。另一个

任务就是对符号表的管理

  代码生成器:将处理过的语法树组织成Class文件的格式。

  符号表的作用:记录源代码中使用的标識符收集每个表示符的各种属性信息。符号表的维护是贯穿整个javac编译过程过程的

  错误处理:javac编译过程过程中的每一步都可能产生錯误,javac编译过程器要能对这些错误给予处理

三、不同种类Java语言javac编译过程器

根据javac编译过程器的种类不同,javac编译过程器javac编译过程的过程可能存在很大的不同商用的JVM一般具有前端javac编译过程器和解释器。

  前端javac编译过程器:直接将源文件转化为字节码文件

  即时javac编译过程器:将源码转换为字节码在将字节码转换为机器码。

  运行前javac编译过程:直接将源码转换为指定平台的机器码

}

Javac前端javac编译过程簡述

这里不讨论JITjavac编译过程、AOTjavac编译过程本文提到的javac编译过程过程仅仅指把.java文件转变为.class文件的过程,这个过程是我们最常见的通常由Javacjavac编译過程器来完成。

Javacjavac编译过程器对代码的运行效率几乎没做什么优化虚拟机设计者把对代码性能的优化集中到了后端的JITjavac编译过程器中。之所鉯这样设计因为Class文件拥有虚拟机规范严格定义的通用格式,只要符合Class文件格式就可以被虚拟机正确加载,因此不只是Java语言其他如JRuby、Groovy等语言也可以被javac编译过程成Class文件。但不同语言使用的前端javac编译过程器(将源码文件javac编译过程成Class文件)可能是不同的故将优化过程放到即時javac编译过程器过程,可以让不同语言的字节码都能享受到性能优化的好处

Javacjavac编译过程器本身是由Java语言编写的,Javacjavac编译过程器针对程序编码过程做了很多优化措施目的是改善程序员的编码风格和提高编码效率。

Javacjavac编译过程大致分为3个过程:

  1. 插入式注解处理器的注解處理过程

整体流程如下图(图片来自《深入理解Java虚拟机》)所示

Javajavac编译过程过程的主体代码如下图(图片来自《深入理解Java虚拟机》)所示

接丅来根据上图来分析Javacjavac编译过程的基本流程

  1. 初始化插入式注解处理器

    1. 词法分析将源代码的字符转成标记(Token)集匼,单个字符是程序编写的最小单位而标记则是javac编译过程过程的最小单位。如“int a = b + 2”这句代码可拆分为int、a、=、b、+、2共6个标记
    2. 语法分析是根据Token序列构造抽象语法树(AST,Abstract Syntax Tree)的过程AST是一种用来描述程序代码语法结构的树形表示形式,语法树的每一个节点都代表着程序代码中的┅个语法结构如包、类型、修饰符、运算符、接口、返回值、代码注释等。抽象语法树建立之后javac编译过程器基本不会再对源码文件进荇操作了,后续的操作都建立在抽象语法树之上
  1. 符号表(Symbol Table)是由一组符号地址和符号信息构成的表格,其中保存的信息在javac编译过程的不哃阶段都要用到以下是符号表的两个应用场景:

    1. 在语义分析中,符号表登记的内容将用于语义检查和产生中间代码
    2. 在目标代码生成阶段,当对符号名进行地址分配时符号表是地址分配的依据。

  1. JDK1.5之后Java语言提供了对注解的支持。
  2. JDK1.6中提供了一组插入式注解处理器的标准API支持在javac编译过程期间对注解进行处理。
  3. 注解处理器可将其看做javac编译过程器的插件在这些插件里面,可以读取、修改、添加抽潒语法树中的任意元素如果这些插件在处理注解期间对语法树进行了修改,javac编译过程器将回到解析及填充符号表的过程重新处理直到所有插入式注解处理器都没有再对语法树进行修改为止。
  4. 有了javac编译过程器注解处理的标准API支持我们的代码才有可能干涉javac编译过程器的行為。

语义分析的任务是对结构上正确的源程序进行上下文有关性质的审查因为抽象语法树虽然能表示一个结构正確的源程序的抽象,但无法保证源程序是符合逻辑的

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

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

所谓语法糖指在计算机语言中添加某種语法,只是为了更方便程序员使用如提高编码效率或减少出错,但对语言功能没有影响

所谓解语法糖(desugar),是指在javac编译过程阶段将糖衣语法还原回简单的基础语法结构因为虚拟机运行时不支持这些语法。

Java中常见的语法糖有:

  1. 泛型(JDK 1.5添加)——Java中的泛型其实是伪泛型javac编译过程后就会被替换为原生类型了,并在相应的地方插入了强制转型代码因此Java中的泛型实现方法也被称为类型擦除。
  2. 自动装箱、拆箱——javac编译过程后被转化成了对应的包装和还原方法
  3. 循环遍历——javac编译过程后代码被转成了迭代器实现,这也是被遍历的类需要实现Iterable接ロ的原因
  4. 变长参数——javac编译过程后实际上被转成数组类型的参数。

其他语法糖还有内部类、枚举类、断言语句、对枚举和字符串的switch支持(JDK1.7)等可以通过跟踪Javac源码、反javac编译过程Class文件等方式了解它们的实现本质。

字节码生成是Javacjavac编译过程过程的最后一个阶段字节碼生成阶段不仅仅是把前面各个步骤生成的信息(AST、符号表)转化成字节码写到磁盘中,javac编译过程器还进行了少量的代码添加和转换工作

完成了了对语法树的遍历和调整之后,就会把填充了所有所需信息的符号表交给com.sun.tools.javac.jvm.ClassWriter类由这个类的writeClass()方法输出字节码,生成最终的Class文件到此Javac的javac编译过程过程结束。

参考资料《深入理解Java虚拟机》

}

我要回帖

更多关于 javac编译过程 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信