java语言的“编译期”其实是一段“不确定”的操作过程,可能是指一个前端编译器把.java变成.class的过程,也可能是指虚拟机的后端运行期编译器(JLT)把字节码转变成机器码的过程,也有可能是使用静态提前编译器(AOT)直接把.java文件直接编译成本地机器代码的过程。现在讨论的是第一种编译器。

Javac编译器

①javac的源码与测试

 

运行com.sun.tools.javac.Main的main()方法来执行编译,与命令行中使用javac的命令没什么区别.

编译过程可以分为3个过程:

1.解析与填充符号表过程

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

3.分析与字节码生成过程

②解析与填充符号表

解析步骤由parseFiles完成。解析步骤包括词法解析与语法解析两个过程

1.词法、语法解析:

词法解析是将字符流转变为标记集合,单个字符是程序编写过程中最小的元素,而标记是编译过程的最小元素,关键字、变量名、字面量、运算符都可以称为标记。

语法分析是根据标记构造抽象语法树的过程,抽象语法树的每一个节点都代表着代码中的一个语法结构,例如包,类型、修饰符、运算符、接口、返回值甚至代码注释等。经过这个步骤以后编译器基本上就不会对源文件进行操作了,后续的操作都建立在抽象语法树之上。

2.填充符号表

③注解处理器

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

④语义分析和字节码生成

语法分析以后,能保证得到一个结构正确的源程序的抽象,但无法保证是符合逻辑的。语义分析的主要任务是对结构上正确的源程序进行上下文有关性质的审查,如进行类型检查。

比如:

int a=;
boolean b=false;
char c=
----------------------------------------------------------------
int d=a+c; //编译通过
int d =b+c;//编译错误
char d=a+c//编译错误

三个操作都能形成正确的语法树,但是却无法通过编译。

 标注检查

语义分析分为标注检查以及数据及控制流分析两个步骤,分别对应attribute方法和flow()方法。

标注检查的内容包括诸如变量使用前是否已被声明、变量和赋值之间的数据类型是否能够匹配等。在标注检查步骤中,还有一个重要的动作称为常量折叠,如果在代码中定义了

int a=+

在语法树上仍然能看到1,2,+,但是经过常量折叠,这个插入式表达式的值已经在语法树上标注出来了。由于编译期间进行了常量折叠,所以在代码里面定义a=1+2和a=3没有什么区别。

数据及控制流分析

对程序上下文逻辑更进一步的验证,可以检查出诸如程序局部变量在使用前是否有赋值、方法的每条路径是否都有返回值、是否所有的受查异常都被正确处理了异常等问题。与类加载时期的数据及控制流分析基本上是一致的,但校检范围由锁区别

//方法1带有final修饰
public void foo(final int arg){ final int var=;
}
//方法2没有final修饰
public void foo(int arg){ int var=;
}

将局部变量在常量池中没有符号引用,也就没有访问标志的信息,因此将局部变量声明为final,对运行期是没有影响的,变量的不变性仅仅有编译器在编译期间保证。

③解语法糖

语法糖指在计算机语言中添加的某种语法,这种语法对语言的功能并没与影响,但是更方便程序员使用。

java中最常用的语法糖主要是泛型、变长参数、自动装箱/拆箱等,虚拟机运行时不支持这些语法,它们在编译阶段还原回简单的基础语法结构,这个过程称为解语法糖。

④字节码生成

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

实例构造器<init>()和类构造器<clinit>()方法就是在这个阶段添加到语法树之中的(这里的实例构造器不是指默认函数,如果用户代码中没有提供任何构造函数,那编译器将会添加一个午餐的构造函数,这个工作在填充符号表节段就已经完成了)。这两个构造器的产生过程实际上是一个代码收敛的过程。

<init>()收敛顺序(这里只讨论非静态变量和语句块)为: 
1. 父类变量初始化 
2. 父类语句块 
3. 父类构造函数 
4. 子类变量初始化 
5. 子类语句块 
6. 子类构造函数

<init>()是在new之后才使用的。

<clinit>()

收敛顺序为: 
1. 父类静态变量初始化 
2. 父类静态语句块 
3. 子类静态变量初始化 
4. 子类静态语句块

<clinit>()是类加载初始化中使用的。

早期(编译器)优化--javac编译器的更多相关文章

  1. 早期javac编译器优化

    学习<深入了解Java虚拟机>有一段时间了,大概理解了Java从源代码编译到执行出结果的过程,也能明确的知道Java是半解释性语言.在执行源代码时,先通过Javac编译器对源代码进行词法分 ...

  2. Javac编译器详解

    学习<深入了解Java虚拟机>有一段时间了,大概理解了Java从源代码编译到执行出结果的过程,也能明确的知道Java是半解释性语言.在执行源代码时,先通过Javac编译器对源代码进行词法分 ...

  3. C++中volatile及编译器优化

    首先看一下单词"volatile"的释义: volatile [ˈvɑlətl] adj.  易变的,不稳定的; (液体或油)易挥发的; 爆炸性的; 快活的,轻快的; 下边是&qu ...

  4. java编译器优化和运行期优化

    概述    最近在看jvm优化,总结一下学习的相关知识 (一)javac编译器 编译过程 1.解析与填充符号表过程 1).词法.语法分析    词法分析将源代码的字符流转变为标记集合,单个字符是程序编 ...

  5. 探索c#之尾递归编译器优化

    阅读目录: 递归运用 尾递归优化 编译器优化 递归运用 一个函数直接或间接的调用自身,这个函数即可叫做递归函数. 递归主要功能是把问题转换成较小规模的子问题,以子问题的解去逐渐逼近最终结果. 递归最重 ...

  6. VS编译器优化诱发一个的Bug

    VS编译器优化诱发一个的Bug Bug的背景 我正在把某个C++下的驱动程序移植到C下,前几天发生了一个比较诡异的问题. 驱动程序有一个bug,但是这个bug只能 Win32 Release 版本下的 ...

  7. 翻译「C++ Rvalue References Explained」C++右值引用详解 Part6:Move语义和编译器优化

    本文为第六部分,目录请参阅概述部分:http://www.cnblogs.com/harrywong/p/cpp-rvalue-references-explained-introduction.ht ...

  8. Visual C++中的编译器优化

    博客搬到了fresky.github.io - Dawei XU,请各位看官挪步.最新的一篇是:Visual C++中的编译器优化.

  9. gcc编译器优化给我们带来的麻烦???

    gcc编译器优化给我们带来的麻烦??? 今天看到一个很有趣的程序,如下: ? 1 2 3 4 5 6 7 8 9 int main() {     const int a = 1;     int * ...

随机推荐

  1. SCons: 替代 make 和 makefile 及 javac 的极好用的c、c++、java 构建工具

    http://scons.org/ https://www.ibm.com/developerworks/cn/linux/l-cn-scons/index.html 后附:另外,WAF是一个基于sc ...

  2. System.Runtime.InteropServices.COMException (0x800A03EC): 无法访问文件

    使用Microsoft.Office.Interop.Excel 操作 今天在服务器部署,操作程序csv文件转xsl文件的时候,遇到一下问题: System.Runtime.InteropServic ...

  3. genstr.py

    #!/usr/bin/python #-*- coding:utf-8 –*- import os import sys import re import shutil import xlrd imp ...

  4. Oracle11g的database 和client的区别是什么?

    由于工作需要,刚开始接触oracle数据库,完全小白,下载的时候看到有database和client两种类型可供下载,一时不知如何是好,于是网上询问得知其中区别,在此记录一下自己的无知. “datab ...

  5. 转载:2.2.4 配置项的单位《深入理解Nginx》(陶辉)

    原文:https://book.2cto.com/201304/19629.html 大部分模块遵循一些通用的规定,如指定空间大小时不用每次都定义到字节.指定时间时不用精确到毫秒. 当指定空间大小时, ...

  6. discuz安装:mysqli_connect()不支持advice_mysqli_connect

    原文:http://blog.csdn.net/changzhi1990/article/details/40983247 php -m 输出: PHP Warning: PHP Startup: U ...

  7. 使用Let's Encrypted HPPTS你的网站

    1.前言 最近,有同事咨询我,怎么样使用Let's Encrypted部署数字证书,于是,结合自己之前的实践,简单总结下. 2.HTTPS的优势 什么加密,防篡改,防广告植入什么的,这个就不多说了.这 ...

  8. activiti 基础

    一:activiti 入门 作者:fenng 商丘 工作流(Workflow) 就是业务过程的部分或整体在计算机应用环境下的自动化主要解决的是"使在多个参与者之间按照某种定义的规则传递文档, ...

  9. Android Rom build.prop文件详解

    # begin build properties   # autogenerated by buildinfo.sh   #以下内容由脚本在编译时自动产生 ro.build.id=6.7.7_97  ...

  10. Hibernate之一级缓存和二级缓存

    1:Hibernate的一级缓存: 1.1:使用一级缓存的目的是为了减少对数据库的访问次数,从而提升hibernate的执行效率:(当执行一次查询操作的时候,执行第二次查询操作,先检查缓存中是否有数据 ...