六 早期(编译期)优化
 
1 “编译期”的含义
    · 可能是指一个前端编译器把*.java文件转变成*.class文件的过程,前端编译器如:Sun的Javac、Eclipse JDT中的增量式编译器(ECJ);
    · 也可能是指虚拟机的后端运行期编译器(JIT编译器)把字节码转变成机器码的过程,JIT编译器如:HotSpot VM的C1、C2编译器;
    · 还可能是指使用静态提前编译器(AOT编译器)直接把*.java文件编译成本地机器码的过程,AOT编译器如:GNU Compiler for the Java(GCJ)、Excelsior JET。
    本部分的编译期指第一种。
    前端编译器在编译期的优化与程序编码关系更加密切,JIT编译器在运行期的优化对程序运行来说更加重要。
 
2 Javac编译器
        ---Javac编译器是一个使用Java语言编写的程序。
        ---编译过程大致可以分为:
            · 解析与填充符号表过程;
            · 插入式注解处理器的注解处理过程;
            · 分析与字节码生成过程。
        ---这三个步骤之间的关系与交互顺序如下图:
                
(1)解析与填充符号表
        1)词法分析和语法分析
                ---词法分析:将源代码的字符流转变成标记(Token)集合。
                ---单个字符是程序编写过程的最小元素,标记是编译过程的最小元素。
                ---标记包括:关键字、变量名、字面量、运算符。
                ---语法分析:根据标记序列构造抽象语法树的过程。
                ---抽象语法树:一种用来描述程序代码语法结构的树形表示方式。语法树的每一个节点都代表着程序代码中的一个语法结构,如包、类型、修饰符、运算符、接口、返回值、代码注释等。
        2)填充符号表
                ---符号表:由一组符号地址和符号信息构成的表格。
                ---符号表中所登记的信息在编译的不同阶段都要用到。在语义分析中,符号表所登记的内容将用于语义检查和产生中间代码;在目标代码生成阶段,当对符号名进行地址分配时,符号表是地址分配的依据。
    (2)注解处理器
            ---在编译期间对注解进行处理,可以读取、修改、添加抽象语法树中的任意元素。若在处理注解期间对语法树进行了修改,编译器将回到解析及填充符号表的过程重新处理,直到所有插入式注解处理器都没有再对语法树进行修改为止。
    (3)语义分析和字节码生成
            ---语义分析:对结构上正确的源程序进行上下文性质的审查,如进行类型审查。
            ---语义分析包括:标注检查和数据及控制流分析两步。
            1)标注检查
                    ---检查的内容包括如变量使用前是否已经被声明、变量与赋值之间的数据类型是否能够匹配、常量折叠等
            2)数据及控制流分析
                    ---是对程序上下文逻辑更进一步的验证,可以检查出诸如程序局部变量在使用前是否有赋值、方法的每条路径是否都有返回值、是否所有的受查异常都别正确处理了等问题。
            3)解语法糖
                    ---Java中常用的语法糖:泛型、变长参数、自动装箱/拆箱、遍历循环、条件编译、内部类、枚举类、断言语句、对枚举和字符串的switch支持、try语句中定义和关闭资源等。
                    ---解语法糖:虚拟机运行时不支持语法糖的语法,它们在编译阶段被还原回简单的基础语法结构。
            4)字节码生成
                    ---不仅仅把前面各个步骤所生成的信息转换成字节码写到磁盘中,编译器还进行了少量的代码添加和转换工作。
                    ---实例构造器<init>()方法和类构造器<clinit>()方法就是在这个阶段添加到语法树之中的。这里的实例构造器不包括默认构造函数,默认构造函数是在填充符号表阶段添加完成的。
                    ---<init>()方法和<clinit>()方法实际上是一个代码收敛的过程,编译器会把语句块({}块或static{}块)、变量初始化(实例变量和类变量)、调用父类的实例构造器(<clinit>()方法中无须调用父类的<clinit>()方法)等操作收敛到<init>()方法和<clinit>()方法中。
                    ---代码替换例子:把字符串的加操作替换成StringBuffer或StringBuilder(取决于JDK版本是否大于等于JDK1.5)的append()操作。
 
3 Java语法糖
    (1)泛型与类型擦除
            ---真实泛型:泛型无论在程序源码中、编译后的中间代码中,还是运行期的代码中,都是切实存在的,这种实现称为类型膨胀,基于这种方法实现的泛型称为真实泛型。
            ---伪泛型:只在程序源码中存在,在编译后的字节码文件中就已经替换为原生类型了,并且在相应的地方插入了强制转型代码,这种实现称为类型擦除,基于这种方法实现的泛型称为伪泛型。
            ---Signature属性存储了一个方法在字节码层面的特征签名,这个属性中保存的参数类型并不是原生类型,而是包括了参数化类型的信息。
            ---擦除法所谓的擦除,仅仅是对方法的Code属性中的字节码进行擦除,实际上元数据中还是保留了泛型信息(在Signature属性中),这也是我们能通过反射手段取得参数化类型的根本依据。
    (2)自动装箱、拆箱、遍历循环与变长参数
                ---遍历循环需要被遍历的类实现Iterable接口的原因:遍历循环在编译之后会还原成迭代器的实现。
                ---变长参数在编译后会还原成数组实现。
                ---自动拆、装箱的陷阱:
                    · 当两个包装类进行比较时,包装类的“==”运算在不遇到算术运算的情况下不会自动拆箱;
                    · 当两个包装类进行比较或一个包装类与另一个基本数据进行比较时,它们的equals()方法不会处理数据转型的关系;
                    · 当一个包装类与一个基本数据类型进行比较或两个基本数据类型进行比较时,"=="运算会自动拆箱、自动类型转换;
                    · 对于Integer类,当值在-128-127之间时,会使用Integer.valueOf()方法直接从缓存中取出相应对象;而当值不在这个范围内时,会使用Integer.valueOf()方法new一个Integer对象。
                ---程序代码为:
                        
                    ---执行结果为:
                            
    (3)条件编译
            ---只能使用条件为常量的if语句才能实现,如果使用常量与其他带有条件判断能力的语句搭配,则可能在控制流分析中提示错误,被拒绝编译。
                    

深入理解Java虚拟机读书笔记6----早期(编译期)优化的更多相关文章

  1. 深入理解Java虚拟机 -- 读书笔记(1):JVM运行时数据区域

    深入理解Java虚拟机 -- 读书笔记:JVM运行时数据区域 本文转载:http://blog.csdn.net/jubincn/article/details/8607790 本系列为<深入理 ...

  2. 【Todo】深入理解Java虚拟机 读书笔记

    有一个在线系列地址 <深入理解Java虚拟机:JVM高级特性与最佳实践(第2版)> http://book.2cto.com/201306/25426.html 已经下载了这本书(60多M ...

  3. 深入理解Java虚拟机读书笔记5----虚拟机字节码执行引擎

    五 虚拟机字节码执行引擎   1 运行时栈帧结构     ---栈帧是用于支持虚拟机进行方法调用和方法执行的数据结构,是虚拟机运行时数据区中的虚拟机栈的栈元素.     ---栈帧中存储了方法的局部变 ...

  4. 深入理解Java虚拟机读书笔记8----Java内存模型与线程

    八 Java内存模型与线程   1 Java内存模型     ---主要目标:定义程序中各个变量的访问规则,即在虚拟机中将变量存储到内存和从内存中取出变量这样的底层细节.     ---此处的变量和J ...

  5. 深入理解Java虚拟机读书笔记7----晚期(运行期)优化

    七 晚期(运行期)优化 1 即时编译器(JIT编译器)     ---当虚拟机发现某个方法或代码块的运行特别频繁时,就会把这些代码认定为“热点代码”,包括被多次调用的方法和被多次执行的循环体.     ...

  6. 深入理解Java虚拟机读书笔记4----虚拟机类加载机制

    四 虚拟机类加载机制 1 类加载机制     ---概念:虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型.     -- ...

  7. 深入理解Java虚拟机读书笔记3----类文件结构

    三 类文件结构 1 Java虚拟机的两种中立特性     · 平台无关性     · 语言无关性     实现平台无关性和语言无关性的基础是虚拟机和字节码存储格式(Class文件).   2 Clas ...

  8. 深入理解Java虚拟机读书笔记1----Java内存区域与HotSpot虚拟机对象

    一 Java内存区域与HotSpot虚拟机对象 1 Java技术体系.JDK.JRE?     Java技术体系包括:         · Java程序设计语言:         · 各种硬件平台上的 ...

  9. 深入理解java虚拟机读书笔记--java内存区域和管理

    第二章:Java内存区域和内存溢出异常 2.2运行时数据区域 运行时数据区分为方法区,堆,虚拟机栈,本地方法栈,程序计数器 方法区和堆是线程共享的区域 虚拟机栈,本地方法栈,程序计数器是数据隔离的数据 ...

随机推荐

  1. web爬虫,requests请求

    requests请求,就是用yhthon的requests模块模拟浏览器请求,返回html源码 模拟浏览器请求有两种,一种是不需要用户登录或者验证的请求,一种是需要用户登录或者验证的请求 一.不需要用 ...

  2. day1||python

    测试题: 0. Python 是什么类型的语言? Python是一种面向对象.解释型.动态类型计算机程序设计语言解释型:程序无需编译成二进制代码,而是在执行时对语句一条一条编译动态类型:在程序执行过程 ...

  3. 在树莓派上的wireshark报错

    QT: XKEYBOARD extension not present on the X server 我在树莓派2b下的vnc远程连接到kali-all(所谓的kali-all就是在kali官方提供 ...

  4. 【转载】【原创】华硕F8TR笔记本更换主板及喇叭教程

    转载地址:http://blog.sina.com.cn/s/blog_6241aaed0102w4e6.html [原创]华硕F8TR笔记本更换主板及喇叭教程     华硕AUSU F8TR笔记本 ...

  5. linux一些工具的安装(二)

    一.Linux下安装lrzsz上传下载工具 1:使用yum安装 yum -y install lrzsz  要有网络才行 输入命令:rz启动文件上传 2:手动编译安装 1. 下载安装包,wget ht ...

  6. A*搜索详解(1)——通往基地的最短路线

    假设地图上有一片树林,坦克需要绕过树林,走到另一侧的军事基地,在无数条行进路线中,哪条才是最短的? 这是典型的最短寻径问题,可以使用A*算法求解.A*搜索算法俗称A星算法,是一个被广泛应用于路径优化领 ...

  7. spring事务详解(二)简单样例

    系列目录 spring事务详解(一)初探事务 spring事务详解(二)简单样例 spring事务详解(三)源码详解 spring事务详解(四)测试验证 spring事务详解(五)总结提高 一.引子 ...

  8. Firebird Embedded 部署的一个坑

    今天把旧程序升级了,把DBX组件换成了FireDac组件,在虚拟机里测试的时候,一直报上图中的错误,但是在主机上运行无问题,之前用户使用也一直没报过这个错. 折腾了又折腾,还是搞不定,感觉脑袋有点大了 ...

  9. OSPF Sham-Link配置示例

    在MPLS/VPN环境中,如果PE-CE之间使用OSPF交换路由信息,OSPF route将作为VPNv4 route(携带OSPF domain ID,OSPF Router ID,OSPF Rou ...

  10. php_screw安装,使用

    安装步骤:1. 下载源码:wget http://nchc.dl.sourceforge.net/project/php-screw/php-screw/1.5/php_screw-1.5.tar.g ...