运行期优化

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



解释器和编译器

当程序需要迅速启动和执行的时候,解释器可以首先发挥作用,省去编译的时间,立即执行。当程序运行后,随着时间的推移,编译器逐渐发挥作用,把越来越多的代码编译成本地代码之后,可以获取更高的执行效率。//解释执行节约内存,编译执行提升效率

解释器还可以作为编译器激进优化时的一个“逃生门”。让编译器根据概率选择一些大多数时候都能提升运行速度的优化手段,当激进优化的假设不成立时,退回解释状态继续执行。因此在整个虚拟机执行架构中,解释器和编译器经常是相辅相成配合工作的。

HotSpot虚拟机中内置了两个即时编译器,称为Client Compiler(C1编译器)和 Server Compiler(C2编译器)。HotSpot虚拟机中默认采用解释器与其中一个编译器直接配合的方式工作,程序使用哪个编译器,取决于虚拟机运行的模式,HotSpot虚拟机会根据自身版本与宿主及其的硬件性能自动选择运行模式,用户也可以使用-client或-server参数去强制指定虚拟机运行在Client模式还是Server模式。

Mixed Mode 混合模式

Interpreted Mode解释模式  -Xint 此时编译器完全不介入

Compiled Mode编译模式   -Xcomp 解释器会在编译无法进行的情况介入

编译对象和触发条件

1.运行过程中会被JIT编译的热点代码有两类

1.1 被多次调用的方法

编译器会对整个方法进行编译,这是虚拟机标准的编译方式

1.2 被多次执行的循环

编译器依然会以整个方法作为编译对象,而这种编译方式发生在方法执行过程中,所以被称为栈上替换(OSR)

2.热点探测的两种方式

2.1基于采样的热点探测,虚拟机周期性地检查各个线程的栈顶,如果发现某个方法经常出现在栈顶,就认为是“热点方法”。优点:简单高效,明确方法调用关系 缺点:容易因为线程阻塞或别的外界因素的影响而扰乱热点探测。

2.2基于计数器的热点探测,虚拟机为每个方法建立计数器,执行次数超过某个阈值,就认为是“热点方法”。优点:统计结果严谨 缺点:需要为每个方法建立并维护计数器,而且不能直接获取到方法的调用关系。

HotSpot虚拟机采用的是第二种,为每个方法准备了两个计数器:方法调用计数器以及回边计数器。这两个计数器都有一个确定的阈值,当计数器超过阈值溢出就会触发JIT编译。

编译优化技术

JDK设计团队几乎把对代码的所有优化措施都集中在了即使编译器上。所以一般来说即时编译器产生的本地代码会比javac产生的字节码更优秀。

语言无关的经典优化技术:公共子表达式消除

语言相关的经典优化技术:数组范围检查消除

最重要的优化技术之一:方法内联

  • 消除了方法调用的成本
  • 为其他优化手段建立了良好的基础
  • 理论上讲只有私有方法、实例构造器、父类方法、静态方法以及final修饰的方法,才能放心的进行内联
  • 如果遇到虚方法,就会向CHA(类型继承关系分析)查询此方法在当前程序下是否有多个目标版本可供选择,如果只有一个,可以进行内联,但是也属于激进优化,需要预留一个逃生门。如果程序的后续执行过程架子啊了导致继承关系发生变化的新类,就要抛弃已经编译的代码,退回解释状态执行,或者重新编译。
  • 如果CHA查询到多个版本的目标方法,则编译器还会使用内联缓存来完成内联,当第一次调用发生后,缓存记录下方法接收者的版本信息,如果每次进行的方法调用版本都是一样的,那这个内联还可以一直使用。但是如果方法接收者不一致,这时候会取消内联,查找虚方法进行方法分派。

最前沿的优化技术之一:逃逸分析(这项技术暂时还不成熟)

当一个对象在方法里面被定义后,它可能被外部方法所引用,这种行为称为方法逃逸。甚至还有可能被外部线程访问到,譬如赋值给类变量或可以在其他线程中访问的实例变量,这种行为称为线程逃逸。

如果能够证明一个对象不会发生逃逸,则可以为这个变量进行一些高效的优化,如:

  • 栈上分配,此时对象会随着方法的结束而自动销毁,垃圾收集系统的压力会小很多。
  • 同步消除,如果一个对象不会逃逸,那么该变量无法被其他线程访问,所以对其进行的读写就不会有竞争,对这个变量实施的同步措施就可以消除。
  • 标量替换,把一个java对象拆散,根据程序访问的情况,将其使用到的成员变量恢复原始类型来访问就叫标量替换,如果对象不会逃逸,而且可以拆分,那么程序真正执行的时候可能不创建这个对象,而改为直接创建它的若干个被这个方法使用的成员变量来替代。

Java与C/C++编译器的对比

  • 即时编译器运行占用的是用户程序的运行时间,具有很大的时间压力,能采用的优化手段有限。
  • java是动态的类型安全语言,意味着虚拟机必须频繁地进行动态检查,如实例方法访问时检查空指针、数组元素访问时检查上下界范围、类型转换时检查继承关系。
  • java中大多数方法都是虚方法,这意味着java即时编译器在进行一些优化(如方法内联)时的难度要远远大于C++等静态优化编译器
  • Java语言可以动态扩展,运行时加载新的类可能改变程序类型的继承关系,这使得很多全局的优化都难以进行。
  • Java语言中对象的内存分配都是在堆上进行的,而C++对象则有多种内存分配方式,将减轻内存回收的压力。

Java语言的这些性能上的劣势都是为了换取开发效率上的优势而付出的代价。而且即时编译器也有静态编译器不能做的优化,由于C++编译器的静态特性,以运行期性能监控为基础的优化措施都不能进行,如调用频率预测、分支频率预测等。

时间: 2024-08-06 11:53:56

运行期优化的相关文章

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

Java语言的“编译期”是一段不确定的过程,因为它可能指的是前端编译器把java文件转变成class字节码文件的过程,也可能指的是虚拟机后端运行期间编译器(JIT)把字节码转变成机器码的过程. 下面讨论的编译期优化指的是javac编译器将java文件转化为字节码的过程,而运行期间优化指的是JIT编译器所做的优化. 编译期优化 虚拟机设计团队把对性能的优化集中到了后端的即时编译器(JIT)中,这样可以让那些不是由javac编译器产生的class文件也同样能享受到编译器优化所带来的好处.但是java

晚期(运行期)优化

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

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

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

JVM晚期运行期优化

最近听我的导师他们讨论Java的即时编译器(JIT),当时并不知道这是啥东西,所以就借着周末的时间,学习了一下! 一.概述 在部分的商用虚拟机(Sun HotSpot)中,Java程序最初是通过解释器(Interpreter)进行解释执行的,当虚拟机发现某个方法或代码块运行的特别频繁时,就会把这些代码认定为"热点代码"(Hot Spot Code).为了提高热点代码的执行效率,在运行时,虚拟机将会把这些热点代码编译成与本地代码相关的机器码,并进行各种层次的优化,完成这个任务的编译器称为

Java虚拟机11:运行期优化

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

JVM总结(六):晚期(运行期)优化

这节我们总结一下JVM运行期的优化问题. JVM运行期优化 即时编译器(JIT) 编译对象与触发条件 编译对象 触发条件 编译过程 编译优化技术 JVM运行期优化 Java程序在运行的期间,可能会有某个方法或者代码块的运行特别频繁时,就会把这些代码认定为“热点代码”.为了提高热点代码的执行效率,在运行时JVM会将这些代码编译成与本地平台相关的机器码,并进行各种层次的优化,完成这个任务的编译器称为即时编译器(Just In Time Compiler,JIT编译器). 即时编译器(JIT) 事实上

JVM-程序编译与代码晚期(运行期)优化

晚期(运行期)优化 1.为了提高热点代码的执行效率,在运行时,虚拟机将会把这些代码编译成与本地平台相关的机器码,并进行各种层次的优化,完成这个任务的编译器称为即时编译器(Just In Time,JIT编译器). 2.Hotspot虚拟机内的即时编译器 (1)解释器与编译器 主流的商用虚拟机,如Hotspot,J9等,都同时包含解释器和编译器. 解释器与编译器两者各有优势:当程序需要快速启动和执行的时候,解释器可以首先发挥作用,省去编译的时间,立即执行.在程序运行后,随着时间得推移,编译器组件发

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

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

c++ 编译期与运行期总结

分享到 一键分享 QQ空间 新浪微博 百度云收藏 人人网 腾讯微博 百度相册 开心网 腾讯朋友 百度贴吧 豆瓣网 搜狐微博 百度新首页 QQ好友 和讯微博 更多... 百度分享 转自:http://hi.baidu.com/zhaoyong200518/item/8516dc59a65be1968d12edff c++ 编译期与运行期总结 一 见识编译期的力量 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 #in