Java编译期优化与运行期优化技术浅析

Java语言的“编译期”是一段不确定的过程,因为它可能指的是前端编译器把java文件转变成class字节码文件的过程,也可能指的是虚拟机后端运行期间编译器(JIT)把字节码转变成机器码的过程。

下面讨论的编译期优化指的是javac编译器将java文件转化为字节码的过程,而运行期间优化指的是JIT编译器所做的优化。

编译期优化

虚拟机设计团队把对性能的优化集中到了后端的即时编译器(JIT)中,这样可以让那些不是由javac编译器产生的class文件也同样能享受到编译器优化所带来的好处。但是javac做了许多针对编码过程的优化措施来改善程序员的编码风格和提高编码效率。许多新生的java语法特性,都是靠编译器的“语法糖”来实现,而不是依赖虚拟机的底层改进来支持。

所以说,java中即时编译器在运行期间的优化过程对于程序的运行来说更重要,而前端编译器在编译期的优化过程对于程序编码来说关系更加密切。

javac编译器的编译过程大致可分为三个步骤:

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

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

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

下面分别来介绍。

解析与填充符号表;

解析步骤包含了词法分析和语法分析两个过程,首先词法分析是将源代码的字符流转变成为标记集合(token),然后语法分析是根据token序列来构造抽象语法树(一种用来描述程序代码语法结构的树状表示方式)。完成词法分析和语法分析之后,下一步是填充符号表,符号表是由一组符号地址和符号信息构成的表格,符号表中所登记的信息在编译的不同阶段都要用到(比如语义分析中符号表所登记的内容将用于语义检查和产生中间代码,目标代码生成阶段当对符号名进行地址分配时,符号表是地址分配的依据)。

插入式注解处理器的注解处理过程:

插入式注解处理器可以看做是一组编译器的插件,在这些插件里面,可以读取、修改、添加抽象语法树中的任意元素。如果这些插件在处理注解期间对语法树进行了修改,那么编译器将回到解析及填充符号表的过程重新处理,直到所有的插入式注解处理器都没有再对语法树进行修改为止。

语义分析与字节码生成过程:

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

1.标注检查

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

2.数据及控制流分析

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

3.解语法糖

语法糖是指在计算机语言中添加某种语法,这种语法对语言的功能并没有影响,但是更方便程序员使用。java中的泛型,变长参数,自动拆箱与装箱,条件编译等就属于语法糖,它们在编译阶段就被还原成简单的语法结构(比如List<String>和List<Integer>在运行期间其实是同一个类)。

4.字节码生成

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

运行期优化

在部分商用虚拟机中,java程序最初是通过解释器进行解释执行的,当虚拟机发现某个方法或代码块运行特别频繁,就会把这些代码认定为“热点代码”,为了提高热点代码的执行效率,在运行时,虚拟机就会把这些代码编译成与本地平台相关的机器码,并进行各种层次的优化,完成这个任务的编译器称为即时编译器或JIT编译器。

即时编译器并不是虚拟机必须的部分,但是即时编译器编译性能的好坏、代码优化程度的高低确是衡量一款商用虚拟机优秀与否的最关键的指标之一。

众多主流的虚拟机都同时包含解释器和JIT编译器,解释器与JIT编译器各有优势:当程序需要迅速启动和执行时,解释器可以首先发挥作用,省去编译的时间,立即执行。当程序运行后,随着事件的推移,JIT编译器逐渐发挥作用,把越来越多的代码编译成本地代码之后,可以获取更高的执行效率。

会被即时编译器编译的热点代码有两类:

1.被多次调用的方法体;

2.被多次调用的循环体。

即时编译器会以整个方法作为编译对象,将其编译成机器码。这种编译方式因为编译发生在方法执行过程之中,因此被称作栈上替换(OSR)。

判断一段代码是否是热点代码的方式(热点探测)有两种:

1.基于采样的热点探测:

此方法会周期性检查各个线程的栈顶,如果发现某个或某些方法经常出现在栈顶,那么这个方法就是热点方法。此方法的缺点是很难精确地确认一个方法的热度,容易受到诸如线程阻塞等因素影响。

2.基于计数器的热点探测:

此方法会为每个方法甚至是代码块建立计数器,统计方法的执行次数,如果执行次数超过一个阀值就认为它是热点方法。

注:默认设置下,执行引擎并不会同步等待编译请求完成,而是继续进入解释器按照解释方式执行字节码,直到提交的请求被编译器编译完成。当编译工作完成之后,这个方法的调用入口地址就会被系统自动改写成新的地址,下一次调用该方法时就会使用已编译的版本。也就是说,在编译器还未完成之前,执行引擎仍按照解释方式继续执行,而编译动作则在后台的编译线程中进行。

优化技术:

一般来说即时编译器所产生的本地代码会比javac产生的字节码更优秀。即时编译器采用了一系列的技术来优化代码,比如公共子表达式消除,数组范围内检查消除,方法内联,逃逸分析等。

时间: 2024-10-13 09:35:44

Java编译期优化与运行期优化技术浅析的相关文章

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

java编译期优化 微信公众号[Java技术江湖]一位阿里 Java 工程师的技术小站.作者黄小斜,专注 Java 相关技术:SSM.SpringBoot.MySQL.分布式.中间件.集群.Linux.网络.多线程,偶尔讲点Docker.ELK,同时也分享技术干货和学习经验,致力于Java全栈开发!(关注公众号后回复”Java“即可领取 Java基础.进阶.项目和架构师等免费学习资料,更有数据库.分布式.微服务等热门技术学习视频,内容丰富,兼顾原理和实践,另外也将赠送作者原创的Java学习指南.

转载:C++编译期多态与运行期多态

前言 今日的C++不再是个单纯的“带类的C”语言,它已经发展成为一个多种次语言所组成的语言集合,其中泛型编程与基于它的STL是C++发展中最为出 彩的那部分.在面向对象C++编程中,多态是OO三大特性之一,这种多态称为运行期多态,也称为动态多态:在泛型编程中,多态基于template(模 板)的具现化与函数的重载解析,这种多态在编译期进行,因此称为编译期多态或静态多态.在本文中,我们将了解: 什么是运行期多态 什么是编译期多态 它们的优缺点在哪 回到顶部 运行期多态 运行期多态的设计思想要归结到

晚期(运行期)优化

晚期(运行期)优化 晚期运行期优化 Start HotSpot虚拟机内的即时编译器 几个问题 解释器与编译器 编译对象与触发条件 编译过程 Client Compiler Server Compiler 查看及分析即时编译结果 编译优化技术 公共子表达式消除 数组边界检查消除 方法内联 逃逸分析 Java与CC的编译器对比 ref Start "热点代码"(Hot Spot Code) – 运行特别频繁的方法或代码块:为了提高热点代码的执行效率,在运行时,虚拟机将会把这些代码编译成与本

Java编译期的前端过程

Java编译期的概念 编译期即将源代码转变成本地代码的过程,对于Java来说,这个过程会更加的多样. Java编译期因为采用的编译器类型不同而导致概念也不同,Java编译器可以分为以下三种类型: 前端编译器 前端编译器将java源代码转变成字节码,常见的前端编译器包括Javac编译器.ECJ编译器(Eclipse JDT). 即时(JIT,Just In Time)编译器 即时编译器将字节码转变成本地机器码,常见的即时编译器包括HotSpot 虚拟机的C1.C2编译器. AOT(Ahead of

Java虚拟机11:运行期优化

前言 http://www.cnblogs.com/xrq730/p/4839245.html,HotSpot采用的是解释器+编译器并存的架构,之前的这篇文章里面已经讲过了,本文只是把即时编译器这块再讲得具体一点而已.当然,其实本文的内容也没多大意义,90%都是概念上的东西,对于实际开发.实际解决项目里面的疑难问题并没有什么太大的帮助,只要看过就好了. 编译对象与触发条件 之前讲过,Sun使用的虚拟机之所以被叫做"HotSpot",就是因为运行过程中会检测热点代码,那么运行过程中,会被

Java编译期和运行期

Q.下面的代码片段中,行A和行B所标识的代码有什么区别呢? ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public class ConstantFolding {       static final  int number1 = 5;       static final  int number2 = 6;       static int number3 = 5;       static int number4= 6;       

运行期优化

在部分商用虚拟机中,Java程序最初是通过解释器进行解释执行的,当虚拟机发现某个方法或代码块运行地特别频繁,就会把这些代码块认定为"热点代码",为了提高热点代码的执行效率,在运行时,虚拟机会把这些代码编译成与本地平台相关的机器码,并进行各种层次的优化,完成这个任务的编译器称为即时编译器(JIT编译器). 解释器和编译器 当程序需要迅速启动和执行的时候,解释器可以首先发挥作用,省去编译的时间,立即执行.当程序运行后,随着时间的推移,编译器逐渐发挥作用,把越来越多的代码编译成本地代码之后,

java编译期和运行期和string原理

 编译期:   是指把源码交给编译器编译成计算机可以执行的文件的过程.在Java中也就是把Java代码编成class文件的过程.编译期只是做了一些翻译功能,并没有把代码放在内存中运行起来,而只是把代码当成文本进行操作,比如检查错误. 运行期:  是把编译后的文件交给计算机执行.直到程序运行结束.所谓运行期就把在磁盘中的代码放到内存中执行起来.在Java中把磁盘中的代码放到内存中就是类加载过程. 通过如String str = "aaa";字面量形式创建的字符串对象 "aaa&

Java编译期和运行期 &amp; JVM

Java整个编译以及运行的过程相当繁琐,本文通过一个简单的程序来简单的说明整个流程. 首先两张图,描述编译和执行的过程: Java代码编译是由Java源码编译器来完成,流程图如下所示: Java字节码的执行是由JVM执行引擎来完成,流程图如下所示: 如下图,Java程序从源文件创建到程序运行要经过两大步骤:1.源文件由编译器编译成字节码(ByteCode)  2.字节码由java虚拟机解释运行.因为java程序既要编译同时也要经过JVM的解释运行,所以说Java被称为半解释语言( "semi-i