网站首页 > java教程 正文
即时编译技术
传统编译只需要为源代码生成对应的机器代码即可,而即时编译是与运行时密切相关的,即编译器需要考虑在何种情况下进行编译、编译完成后机器代码如何被虚拟机使用等。接下来将简单介绍即时编译涉及的一些技术。
分层编译
非此即彼的两个即时编译器可能不是最佳选择。那么,是否有一种编译技术可以综合实现解释器的快速启动、C1的快速预热和C2的高性能产出呢?可以使用-XX:+TieredCompilation开启分层编译,它额外引入了四个编译层级。
1)第0级:解释执行。
2)第1级:C1编译,开启所有优化(不带Profiling)。
3)第2级:C1编译,带调用计数和回边计数的Profiling信息(受限Profiling)。
4)第3级:C1编译,带所有Profiling信息(完全Profiling)。
5)第4级:C2编译。
常见的分层编译层级转换路径如图7-1所示。
- 0→3→4:常见层级转换。用C1完全编译,如果后续方法执行足够频繁再转入4级。
- 0→2→3→4:C2编译器繁忙。先以2级快速编译,等收集到足够的Profiling信息后再转为3级,最终当C2不再繁忙时再转到4级。
- 0→3→1/0→2→1:2/3级编译后因为方法不太重要转为1级。如果C2无法编译也会转到1级。
- 0→(3→2)→4:C1编译器繁忙,编译任务既可以等待C1也可以快速转到2级,然后由2级转向4级。
在JDK 7及之前版本中,可以使用-XX:CompileThreshold=<val>调整编译一个方法的时机,但是在开启分层编译后,该参数会被忽略,判断一个方法是否编译的条件不再基于单个参数,而是综合考虑一系列因素和多个参数,类似于下面的公式:
Predicate(i, b) = (i > Tier3InvocationThreshold)或者(i > Tier3MinInvocationThreshold and i+b> Tier3CompileThreshold)
其中i表示方法调用的次数,b表示回边发生的次数,-XX:Tier3ComilpeThreshold默认为2000。
栈上替换
模板解释器使用方法计数和回边计数识别热点,其中,方法计数识别热点方法,回边计数识别热点循环,如图7-2所示。
一个合理的猜想是编译器识别出热点代码然后进行编译,等待编译完成,在下一次调用时,可直接调用编译后的机器代码代替解释执行。
但在实际情况中并不总是有“下一次调用”的机会。假如有一个包含了千万次的循环方法,方法只执行一次,此时如果等待方法执行完成再进行编译,由于方法只调用一次,编译器将没有机会使用编译后的代码。
为了防止编译器做这种无用功,需要一种技术在解释执行循环期间将代码替换为编译后的代码,即循环的第N次使用解释执行,第N+1次使用编译后的代码,这样就能将“下一次调用”缩小到“下一次循环”。这种技术叫作栈上替换(On Stack Replacement,OSR)。OSR机制类似协程切换,它将解释器栈的数据打包到OSR buffer,然后在编译后的代码里面提取OSR buffer的数据放入编译后的执行栈,再继续执行。
退优化
虚拟机执行方法或循环的次数越多,它知道的代码的额外信息就越多。假设虚拟机执行了很多次obj.equals()发现obj的类型都是String,那么虚拟机可以乐观地认为obj就是String类型,继而直接调用String.equals,省去了查询obj虚函数表的开销。但是如果后续变量obj接收到其他类型的对象,虚拟机也必须有处理这种少数情况的能力,这种处理少数情况的行为即退优化。
除了上述这个例子外,编译器优化还会做很多乐观的假设,它广泛使用fast/slow惯例,乐观地认为大部分情况程序都是走快速路径fast,而只有极少数情况走慢速路径slow。当极少数情况发生时,虚拟机将执行退优化,使用慢速路径作为后备方案。退优化可以认为是栈上替换的逆操作。
本文给大家讲解的内容是深入解析java虚拟机:编译概述,即时编译技术
- 下篇文章给大家讲解的是深入解析java虚拟机:编译概述,编译理论基础;
- 觉得文章不错的朋友可以转发此文关注小编;
- 感谢大家的支持!
- 上一篇: 在.Net中使用Java代码?
- 下一篇: 掌握这些Maven命令,让你的Java项目开发更高效!
猜你喜欢
- 2024-11-17 Maven 干货: 简单两步,Maven Wrapper 接管你的Java项目编译!
- 2024-11-17 Java字节码指令:invokestatic(0xB8)
- 2024-11-17 Java小白入门教程(2)——基本语法&变量
- 2024-11-17 Jvm从编译到执行
- 2024-11-17 这样做优化,实现 0.059s 启动一个SpringBoot项目
- 2024-11-17 Java 8:一文掌握 Lambda 表达式 | CSDN 博文精选
- 2024-11-17 面试官:Java从编译到执行,发生了什么
- 2024-11-17 五、编写第一个Java程序
- 2024-11-17 掌握这些Maven命令,让你的Java项目开发更高效!
- 2024-11-17 在.Net中使用Java代码?
你 发表评论:
欢迎- 最近发表
-
- 搞趣网:我的世界全新皮肤包原始居民下载地址
- 我的世界拔刀剑MOD下载(我的世界拔刀剑mod下载国际版)
- 我的世界无正版账号的简单联机方法(非网易版,仅适用于局域网)
- 一些可以显著提高大型 Java 项目启动速度的尝试
- 常见的java敏感异常介绍(java 常见的异常)
- Java 开发者必看!三招实现外部 Jar 包动态加载(含热更新方案)
- Java JAR 启动内存参数配置指南:从基础设置到性能优化
- 对Spring MVC接口进行Mock测试(springmvc对外接口)
- 还在用策略模式解决 if-else?Map+函数式接口方法才是YYDS
- 干掉OpenFeign,SpringBoot 3.0 自带的 HTTP 客户端真香!
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)