Javac的实现过程

主要介绍Javac的实现过程及原理。

首先弄明白什么是Javac?

Javac是一种编译器,将一种语言转换为另一种语言规范。编译器的作用就是将符合java语言规范的源代码转化为JVM虚拟机能够识别的字节码文件的过程。

对于java而言。javac任务就是将java源代码转换为jvm能够识别的二进制码。将.java文件转换为.class文件,这些.class文件也就是字节码文件只有JVM能够识别。

编译过程的原理:

1、词法分析:首先将源代码按照字节的方式读取,然后找出定义的语法关键字(if/else/for等),然后判断哪些关键字是符合java语言规范的,经过整理分析返回一些规范化的Token流

2、语法分析:对Token流进行分析。分析出这些关键字组合在一起是否符合java语言规范,经过分析之后会产生一个符合java规范的抽象语法树。抽象语法树就是一个结构化的语法表达式,作用就是将词法用一个结构化的形式组合在一起。

Java的语法树使java源码更加结构化,每个语法树上的节点都是一个JCTree实例

JCTree类有三个重要属性:其实这三个属性很好理解,为了分辨出树中的每一个节点而出现的,定义了这三个属性,可以很快速的找到节点在树中的层次结构和位置。

  1. TreeTag:每个语法数节点都用整形常熟表示,每个节点数值都是在前一个节点的基础上执行加一操作,顶点节点TopLevel是1,那紧接着的Import节点就在TopLevel的基础上加一,等于2  
  2. pos:整数。表示位置
  3. type:表示节点的类型

3、语义分析:对生成的抽象结构树进一步分析,将复杂的语法结构转换为简单的,易于理解和阅读的语法结构。例如:将增强for循环foreach转换为for循环结构。经过语义分析之后会产生一个更加具体的抽象结构树。

语义分析实现的步骤;

语义分析主要是在Enter类中完成的,这个类主要有两个步骤

(1)将所有类中出现的符号都输入到类自身的符号表中,所有的类符号,类参数列表,超类符号,和继承的接口类型符号都会存储到未处理的符号列表中(因为类除了自身的符号之后还有其他类中的引用,所以要进行分类)

(2)在未处理的符号列表中,将所有类符号解析到各自的类符号中,在MemberEnter.complete()类中完成。(解析语法树,将所有的符号都添加到符号表中)

在Enter类解析的步骤中,还有一个辅助操作:

  • 添加默认的构造函数;
  • 接着下一步是处理注解:在JavaProcessingEnvironment类中完成;
  • 数据流分析,在Flow类中完成。  

    数据流分析实现的步骤:

    1、检查变量在使用之前是否赋值,除了8中基本数据类型之外,还有String类型和其他对象的引用在使用之前都需要赋值。

    2、使用final修饰的变量不会被重新赋值,如果重复复制会报错;同时如果变量是静态成员变量在定义的时候就必须赋值

    3、分析方法返回值类型

    4、所有的Checked Exception都必须向上抛出或者捕获。

    5、所有的语句都会被执行,这个分析的是return语句之后是否还有语句,因为return之后的语句不会被执行。

  • 语义分析器的最后一个步骤,进一步处理语法树,解决的问题
    •   消除无用的代码,例如:if条件永远为false不会被执行的代码块  
    •         解除语法糖:说白了就是将例如增强的foreach循环转换为for循环
    •         变量自动类型转换:例如:int类型和Integer类型之间相互转换

4、字节码:经过了上面的三个步骤之后,java源代码就可以被转换成为java虚拟机(JVM)能够别的字节码文件。

代码生成器:

  •   将源代码转换成符合JVM语法规范的命令形式,JVM的所有操作都是基于栈操作的,因此所有的操作都在进栈和出栈中完成。
  •         按照JVM文件组织的形式将字节码输出到后缀名为class的字节码文件中

整个业务流程:

 关于javac的基本原理就介绍到这里,有兴趣的可以研究下Javac的源码,可以从OpenJdk下载到源码。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏C/C++基础

C++inline函数简介

inline函数是由inline关键字来定义,引入inline函数的主要原因是用它替代C中复杂易错不易维护的宏函数。

1342
来自专栏everhad

札记:Java异常处理

异常概述 程序在运行中总会面临一些“意外”情况,良好的代码需要对它们进行预防和处理。大致来说,这些意外情况分三类: 交互输入 用户以非预期的方式使用程序,比如...

2338
来自专栏前端儿

ES6笔记(5)-- Generator生成器函数

Generator的声明方式类似一般的函数声明,只是多了个*号,并且一般可以在函数内看到yield关键字

861
来自专栏java达人

Java 8 Stream 教程 (一)

作者:Benjamin 译者:java达人 来源:http://winterbe.com/posts/2014/07/31/java8-stream-tut...

30710
来自专栏程序员互动联盟

【编程基础第九讲】main函数也有参数?

存在问题: main函数我们使用的多关注的少,特别是参数,如何去用? 解决方案: 有C语言初学者朋友不知道怎么应用main函数的参数,其实也不难,只要对C语言...

34813
来自专栏章鱼的慢慢技术路

《算法图解》第二章笔记与课后练习

17510
来自专栏黑泽君的专栏

Java培训实战教程之Java基础知识精华部分(一)(二)(三)

682
来自专栏技术沉淀

Python: itertools模块任性迭代

1202
来自专栏技术博客

C#项目代码规范

   小菜就是小菜,几个人搞出来的项目,让公司大牛稍微看了下,最后送出了惨不忍睹四个字。命名各种各样,五花八门,大写英文、小写英文、大写拼音、小写拼音、英文和拼...

1234
来自专栏Java开发者杂谈

Ruby(1):入门

安装:   一般来说linux会自动装ruby,可以通过:   ruby -v 来查看ruby版本   直接使用ruby命令的话,是用来执行ruby文件的。如果...

3578

扫码关注云+社区