学习《深入了解Java虚拟机》有一段时间了,大概理解了Java从源代码编译到执行出结果的过程,也能明确的知道Java是半解释性语言。在执行源代码时,先通过Javac编译器对源代码进行词法分析、语法分析、生成抽象语法树、语义分析等,这部分操作是在Java虚拟机之外进行的,而解释器在虚拟机内部,所以Java程序的编译就是半独立的实现过程。

一、了解一下javac编译的详解过程

编译过程大致上分为三步:解析与填充符号表过程、插入式注解处理器的注解处理过程、分析与字节码生成过程。

(1)词法、语法分析

  词法分析是将源代码的字符流转变为标记(Token)集合,单个字符是程序编写过程的最小元素,而标记则是编译过程的最小元素,关键字、变量名、字面量、运算符都可以称为标记,如“int a = b + 2”这句代码包含了6个标记,不可拆分,分别为int、a、=、b、+、2,虽然关键字int由3个字符构成,但是它只是一个标记(Token),不可再拆分。

  语法分析是根据Token序列构成抽象语法树的过程,抽象语法树(Abstract Syntax Tree)是一种用来描述程序代码语法结构的树形表示方式,语法树的每一个节点都代表着程序中的一个语法结构(Construct),例如包、类型、修饰符、运算符、接口、返回值甚至代码注释等都可以是一个语法结构。

(2)符号填充表(目前这点知识我不是很理解)

  完成词法分析和语法分析后,下一步就是填充符号表的过程,符号表(Symbol Table)是由一组符号地址和符号信息构成的表格,可以将它想象成哈希表中K-V键值对的形式(实际上符号表不一定是哈希表实现,可以是有序符号表、树状符号表、栈结构符号表等)。符号表中所登记的信息在编译的不同阶段都要用到。在语义分析中,符号表所登记的内容将用于语义检查(如检查一个名字的使用和原先的说明是否一致)和产生中间代码。在目标代码生成阶段,当对符号表名进行地址分配时,符号表是地址分配的依据。

(3)注解处理器

  在JDK 1.5之后,Java语言提供了对注解(Annotation)的支持,这些注解与普通的Java代码一样,是在运行期间发挥作用的。在JDK 1.6中提供了一组插入式注解处理器的标准API在编译期间对注解进行处理,我们可以把它看做是一组编译器的插件,在这些插件里面可以读取、修改、添加抽象语法树中的任意元素。如果这些插件在处理注解期间对语法树进行修改,编译器将回到解析及填充符号表的过程重新处理,直到所有插入式注解处理器都没有再对语法树进行修改为止,每一次循环称为一个Round,也就是上图的回环过程。

  有了编译器注解处理器的标准API后,我们的代码才有可能干涉编译器的行为,由于语法树中的任意元素,甚至包括代码注释都可以在插件中访问到,所以通过插入式注解处理器实现的插件功在功能上有很大的发挥空间。

(4)语义分析与字节码生成

  语义分析之后,编译器获得了程序代码的抽象语法树表示,语法树能表示一个结构正确的源程序的抽象,但无法表示源程序是否符合逻辑。而语义分析的主要任务是对结构上正确的源程序进行上下文有关性质的审查,如进行类型审查!

  javac分析过程分为标注检查以及数据及控制流分析;

  a) 标注检查

int a = 1;
boolean b = false;
char c = 2;

  后续可能会出现的赋值运算:

int d = a + c;
int d = b + c;
char d = a + c;

   后续代码中如果出现了如上3中赋值运算的话,那它们都能构成结构正确的语法树,但是只有第1种的写法在语义上是没有问题的,能够通过编译,其余两种在Java语言中是不合逻辑的,无法编译(是否符合语义逻辑必须在具体的语言与具体的上下文环境之中才有意义)。

  b) 数据及控制流分析

  数据及控制流分析是对程序上下文逻辑更近异步的验证,它可以检查出诸如程序员局部变量在使用前是否有赋值、方法的每条路径是够都有返回值、是否所有的受查异常都被正确处理了等问题。有一些校验只有在编译期或运行期才能进行!  

  c) 语法糖

  语法糖是指在计算机语言中添加的某种语法,这种语法对语言的功能没有影响,但是更方便程序员的使用。Java中最常用的语法糖主要是泛型、变长参数、自动装箱/拆箱、条件编译等,虚拟机不支持这些语法,他们在编译阶段还原回简单的基础语法结构(泛型的擦除、变长参数封装成数组参数、Integer自动装箱拆箱变为Integer.value()等、分支不成立的代码块清除掉)。

(4)字节码生成

  字节码生成是Javac编译过程的最后一个阶段,在Javac源码里面有com.sun.tools.javac.jvm.Gen类完成。字节码生成阶段不仅仅是把前面各个步骤所生成的信息(语法树、符号表)转化为字节码写到磁盘中,编译器还进行了少量的代码添加和转换工作。  

二、Java语法糖的味道

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

  1. 早期(编译器)优化--javac编译器

    java语言的“编译期”其实是一段“不确定”的操作过程,可能是指一个前端编译器把.java变成.class的过程,也可能是指虚拟机的后端运行期编译器(JLT)把字节码转变成机器码的过程,也有可能是使用 ...

  2. Javac编译器详解

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

  3. 《深入理解Java虚拟机》-----第10章 程序编译与代码优化-早期(编译期)优化

    概述 Java语言的“编译期”其实是一段“不确定”的操作过程,因为它可能是指一个前端编译器(其实叫“编译器的前端”更准确一些)把*.java文件转变成*.class文件的过程;也可能是指虚拟机的后端运 ...

  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. centos8平台给sudo配置日志

    一,sudo日志的用途: 我们可以记录下来用户账号在哪个时间进行过sudo 这样不需要再从secure日志中查找用户的sudo记录 说明:刘宏缔的架构森林是一个专注架构的博客,地址:https://w ...

  2. 编译安装tree命令

    查看当前的tree [12:33:33 root@C8[ ~]#rpm -qi tree Name : tree Version : 1.7.0 Release : 15.el8 Architectu ...

  3. xUtils简介和使用方法

    xUtils简介 xUtils 包含了很多实用的android工具. xUtils 最初源于Afinal框架,进行了大量重构,使得xUtils支持大文件上传,更全面的http请求协议支持(10种谓词) ...

  4. 线程池FixedThreadPool

    可重用线程池,只有核心线程,并发无阻塞, public class MainActivity extends AppCompatActivity { @Override protected void ...

  5. MFiX做增量编译的时候不要删掉*.mod和*.inc文件

    其实之前发现了这个问题,但是没有记录,过了好久又忘了.具体问题是,在做增量编译的之前,都会习惯性地删除多余文件再编译,随手就把*.mod和*.inc这类中间文件也删了,结果修改完代码执行 make - ...

  6. 赛门铁克和DigiCert证书有什么区别?

    在众多国人眼里,赛门铁克Symantec名气更胜于DigiCert证书.但是,我们知道2017年赛门铁克因一系列原因被DigiCert收购,品牌名称也被更新为DigiCert Secure Site. ...

  7. C2. Pokémon Army (hard version) 解析(思維)

    Codeforce 1420 C2. Pokémon Army (hard version) 解析(思維) 今天我們來看看CF1420C2 題目連結 題目 略,請直接看原題. 前言 根本想不到這個等價 ...

  8. Java学习的第二十四天

    1. 目录管理 2.文件方法太多记不清 3.明天学习流和流的分类

  9. Linux 网络编程的5种IO模型:多路复用(select/poll/epoll)

    Linux 网络编程的5种IO模型:多路复用(select/poll/epoll) 背景 我们在上一讲 Linux 网络编程的5种IO模型:阻塞IO与非阻塞IO中,对于其中的 阻塞/非阻塞IO 进行了 ...

  10. python爬虫中的requests模块

    Requests: 让 HTTP 服务人类 一.简介 虽然Python的标准库中 urllib 模块已经包含了平常我们使用的大多数功能,但是它的 API 使用起来让人感觉不太好,而 Requests ...