早期(编译期)优化

一、Javac编译器

  1.Javac的源代码与调试

    Javac的源代码放在JDK_SRC_HOME/langtools/src/shares/classes/com/sun/tools/javac中,除了JDK自身的API之外,就只引用了JDK_SRC_HOME/langtools/src/shares/classes/com/sun/*里面的代码,调试环境建立起来简单方便,因为基本上不需要处理依赖关系。

    编译过程大致可以分成3个过程:

    (1)解析与填充符号表过程

    (2)插入式注释处理器的注解过程处理

    (3)分析与字节码生成过程

    Javac编译动作的入口是com.sun.tools.javac.main,JavaCompikler类,上述3个过程的代码逻辑集中在这个类的compiler()和compiler2()方法中。

  2.解析与填充符号表

    解析步骤包括词法分析和语法分析两个过程

  (1)词法、语法分析

词法分析是将源代码的字节流变成标记(Token)集合,单个字符是程序编码过程的最小元素,而标记则是编译过程的最小元素。

    在Javac的源代码中,词法分析过程由com.sun.tools.javac.parser.Scanner类来实现。

    词法分析是根据Token序列构造抽象语法树的过程,抽象语法是一种用来描述程序代码语法结构的树形表示方式,语法树的每一个节点都代表着程序代码中的一个语法结构。

    语法分析过程由com.sun.tools.javac.parser.Parse类来实现,这个阶段产生出抽象语法树有com.sun.tools.javac.tree.JTree类表示,经过这个步骤之后,编译器就基本不会再对源代码文件进行操作了,后续的操作都建立在抽象语法树上。

   (2)填充符号表

      符号表(Symbol Table)是由一组符号地址和符号信息构成的表格。

      在语法分析中,符号表所登记的内容将用于语法分析检查和产生中间代码。

      在目标代码生成阶段,当对符号名进行地址分配时,符号表是地址分配的依据。

      在Javac源代码中,填充符号表的过程由com.sun.tools.javac.compiler.Enter类来实现,此过程的出口是一个待处理列表(ToDoList),包含;了每一个编译单元的抽象语法树的顶级节点以及package-info-java的顶级节点。

  3.注解处理器

    在Javac源码中,插入式注解处理器的初始化过程是在initProcessAnnotations()方法中完成的,而它的执行过程则是在ProcessAnnotations()方法中完成的。这个方法判断是否有新的注解处理器需要执行,如果有的话,通过com.sun.tools.javac.Processing.JavacProvcessingEnviroment类的doProcessing()方法生成一个新的JavaCompiler对象对编译的后续步骤进行处理。

  4.语义分析与字节码生成

    (1)标注检查:内容包括诸如变量使用前后是否已被声明,变量与赋值之间的数据类型是否能够匹配等。在标注检查步骤中,还有一个重要的动作,称为常量折叠。

      标注检查步骤在javac源代码中实现类是com.sun.tools.javacComp.Attr类和com.sun.tools.javac.comp.Check类。

    (2)数据及控制分析

      对程序上下文逻辑更进一步的验证,它可以检查出诸如程序局部变量在使用前后是否有赋值,方法的每一条路径是否都有返回值,是否所有的受检查异常都被正确出来了等问题。

      在Javac的源代码中,数据及控制流分析的入口是flow()方法,具体操作是由com.sun.tools.javac.comp.Flow类来完成的。

    (3)解语法糖

      语法糖(Syntatic Sugar),也称糖衣语法,指在计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,但是更方便使用。

      在Javac的源代码中,解语法糖的过程由的desugar()方法触发,在com.dun.tools.javac.comp.TransTypes类和com.sun.tools.javac.comp.Lower类中完成。

    (4)字节码生成

      字节码生成是Javac编译过程的最后一个阶段,在Javac源代码里面有com.sun.tolls.javac.jvm.Gen类来完成。

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

二、Java语法糖

  1.泛型与类型擦除

    C#里面泛型无论在程序源码中,编译后的IL中,货值运行期的CLR中,都是切实存在的,List<int>与List<string>就两个不同稍微类型,它们在系统运行期生成,有自己的虚方法表和,类型数据,这种实现机制称为类型膨胀,基于这种方法实现的泛型称为真是泛型。

    Java语言中的泛型不一样,它只在程序源代码中存在,在编译后的字节码文件中,就已经替换为原来的原生类型了,并且在相应的地方插入了强制转型代码,因此,对于运行期的Java语言来说,ArrayList<String>与ArrayList<int>就是同一个类,所以泛型技术实际上是Java语言的一颗语法糖,java语言中的泛型实现方法称为类型擦除,基于这种方法的泛型称为伪泛型。

    虚拟机规范中引入了诸如Signature,LocalVariableType等新的属性用于解决伴随泛型而来的参数类型识别问题。

  2.自动装箱、拆箱与遍历循环

  自动装箱、拆箱在编译之后转化成了对应的包装盒还原方法,而遍历循环则把代码还原成迭代器的实现。

  包装类的“==”运算在不遇到算术符运算的情况下不会自动拆箱,以及它们equals()方法不处理数据转型的关系。

  3.条件编译

  Java语言可以进行条件编译,方法就是使用条件为常量的if语句。

  Java语言中条件编译的实现是,Java语言的一颗语法糖,根据布尔常量的真假,编译器将会把分支中不成立的代码清除掉。这一项工作将在编译器解除语法糖阶段(com.sun.tools.javac.comp.Lower类中)实现。

JVM-程序编译与代码早期(编译期)优化的更多相关文章

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

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

  2. (转)unity3D 如何提取游戏资源 (反编译)+代码反编译

    原帖:http://bbs.9ria.com/thread-401140-1-1.html 首先感谢 雨松MOMO 的一篇帖子 教我们怎么提取 .ipa 中的游戏资源.教我们初步的破解unity3d资 ...

  3. 小师妹学JVM之:深入理解JIT和编译优化-你看不懂系列

    目录 简介 JIT编译器 Tiered Compilation分层编译 OSR(On-Stack Replacement) Deoptimization 常见的编译优化举例 Inlining内联 Br ...

  4. JVM性能优化系列-(5) 早期编译优化

    5. 早期编译优化 早起编译优化主要指编译期进行的优化. java的编译期可能指的以下三种: 前端编译器:将.java文件变成.class文件,例如Sun的Javac.Eclipse JDT中的增量式 ...

  5. Javac早期(编译期)

    从Sun Javac的代码来看,编译过程大致可以分为3个过程: 解析与填充符号表过程. 插入式注解处理器的注解处理过程. 分析与字节码生成过程. Javac编译动作的入口是com.sun.tools. ...

  6. 深入了解JVM虚拟机8:Java的编译期优化与运行期优化

    java编译期优化 java语言的编译期其实是一段不确定的操作过程,因为它可以分为三类编译过程:1.前端编译:把.java文件转变为.class文件2.后端编译:把字节码转变为机器码3.静态提前编译: ...

  7. 【深入理解JAVA虚拟机】第4部分.程序编译与代码优化.1.编译期优化。这章编译和实战部分没理解通,以后再看。

    1.概述 1.1.编译器的分类 前端编译器:Sun的Javac. Eclipse JDT中的增量式编译器(ECJ)[1].  把*.java文件转变成*.class文件 JIT编译器:HotSpot ...

  8. Android 程序分析环境搭建-Android 9 -代码下载编译

    Android 9 -代码下载编译 一,翻墙下载: 1.背景: 背景: 现在Android framework 开发的同学,整体在公司里面解一些无关痛痒的bug,对于Android framework ...

  9. java编译期优化

    java语言的编译期其实是一段不确定的操作过程,因为它可以分为三类编译过程: 1.前端编译:把.java文件转变为.class文件 2.后端编译:把字节码转变为机器码 3.静态提前编译:直接把*.ja ...

随机推荐

  1. sof文件和NIOS II的软件(elf)合并为jic文件以使用Quartus Programmer烧写

    将Altera FPGA的sof文件和NIOS II的elf固件合并为一个jic文件以使用Quartus Programmer烧写   我们在学习和调试NIOS II工程的时候,一般都是先使用Quar ...

  2. POJ 2195:Going Home(最小费用最大流)

    http://poj.org/problem?id=2195 题意:有一个地图里面有N个人和N个家,每走一格的花费是1,问让这N个人分别到这N个家的最小花费是多少. 思路:通过这个题目学了最小费用最大 ...

  3. Python—Socket

    Socket模块 socket通常也称作"套接字",用于描述IP地址和端口,是特定网络协议如TCP/IP.UDP/IP套件对网络应用程序提供者提供的当前可移植标准的对象, 用来连接 ...

  4. Linux命令学习整理。

    http://www.cnblogs.com/suliuer/p/5448747.html 本文主要包括两部分,一是Linux基础命令的总结:二是总结一些常用的命令知识点. 一.基础总结 学习Linu ...

  5. 控制边框颜色:《CSS3 Border-color》

    CSS3中有关于Border的属性一共有三个:圆角border-radius,图片边框border-images,边框多颜色border-color,其中圆角border-radius是常用的一个属性 ...

  6. 如何使用double-check实现一个单例模式

    private object m_mutex = new object(); private bool m_initialized = false; private BigInstance m_ins ...

  7. [四校联考P3] 区间颜色众数 (主席树)

    主席树 Description 给定一个长度为 N 颜色序列A,有M个询问:每次询问一个区间里是否有一种颜色的数量超过了区间的一半,并指出是哪种颜色. Input 输入文件第一行有两个整数:N和C 输 ...

  8. 关于SQLite数据库的作业

    数据库的SQL预览代码我忘了复制了 只能截图 Students表: Course表: Score表: Teachcer表:

  9. EasyUI中动态生成标签页

    这是最近学到的内容,当时是有思路但是不知道怎么获取当前的点击对象,就没有实现功能,通过更深入的学习,我知道了不仅仅是Java,Oracle中有一个this,同样的EasyUI中也存在一个this,来获 ...

  10. 左边图标右边文字,在div里居中