当前位置: 首页 > news >正文

Java即时编译器(JIT)的原理及在美团的实践经验

基本功 | Java即时编译器原理解析及实践 - 美团技术团队

这篇文章由美团AI平台/搜索与NLP部的珩智、昊天、薛超撰写,深入介绍了Java即时编译器(JIT)的原理及在美团的实践经验。

  1. Java执行过程与即时编译器概述
    • Java执行过程:Java先由javac编译成字节码(前端编译),再由解释器逐条解释执行。执行中,虚拟机收集程序运行信息,编译器对热点代码(方法或代码块调用次数超阈值)进行后端编译,将字节码转为机器码存入codeCache,下次执行直接读取,提升性能。
    • JVM中的编译器:集成Client Compiler(C1)和Server Compiler。C1注重启动速度和局部优化,将字节码转为HIR再到LIR生成机器码;Server Compiler关注全局优化,性能更好但启动慢,包括C2和Graal。C2用Ideal Graph优化,Graal在分支预测等激进优化上表现更优,对Java新特性友好,从JDK 9集成,可通过特定参数启用替换C2。
    • 分层编译:Java 7引入,结合C1和C2优势,将JVM执行状态分五层,JVM根据服务运行情况选择编译路径,从解释执行开始,到达终止状态(1层和4层)停止编译请求。JDK 8默认开启分层编译。
    • 即时编译的触发:Java虚拟机根据方法调用次数和循环回边执行次数触发即时编译。分层编译时,触发条件基于特定参数和系数动态判断,JVM会调整系数 。
  1. 编译优化技术
    • 中间表达形式:Java字节码是一种IR,但现代编译器常用图结构的IR,如SSA IR。C1使用HIR和LIR(均为SSA形式)优化,C2的Ideal Graph采用Sea-of-Nodes IR(SSA形式),通过Phi Nodes解决不同路径变量赋值问题,GVN利用这种结构简化等价计算优化。
    • 方法内联:编译时将目标方法体纳入编译范围取代原调用,减少方法调用开销,是JIT重要优化手段。内联有条件限制,可通过参数调整内联层数。虚函数内联较难,C2对部分虚调用可优化,Graal通过收集信息提升多实现虚调用的执行效率。
    • 逃逸分析:确定对象指针动态范围,判断对象是否逃逸出线程或方法,基于此可进行锁消除、栈上分配和标量替换优化。Graal还进行部分逃逸分析,在部分路径优化。
    • Loop Transformations:C2编译器对循环进行优化,循环展开通过减少循环指令提升速度,循环分离将特殊迭代分离减少开销 。
    • 窥孔优化与寄存器分配:窥孔优化替换相邻指令为高效指令组,寄存器分配将频繁使用变量存于寄存器提升速度,二者是编译优化最后一步,之后生成机器码存入codeCache。
  1. 实践经验
    • 编译相关重要参数:如开启分层编译、设置编译线程数、各层编译阈值、codeCache大小等参数,一般不建议手动调整,特定情况(如codeCache满、方法未内联影响性能)可调整。
    • 通过JITwatch分析编译日志:添加特定参数输出编译日志,用JITwatch工具分析,可查看项目Java Class、编译时间轴、代码优化建议、逃逸分析优化结果等信息。
    • 使用Graal编译器:用特定参数可启用Graal编译器代替C2,它与G1搭配使用,在美团线上服务中,启用后TP9999下降,峰值性能提升,但启动时性能差。可通过静态编译提升启动速度,但GraalVM的垃圾回收性能欠佳,对Java部分特性支持不足,仍需调研。
  1. 总结:JIT技术已较成熟,在Java服务中JVM已做很多优化,但深入了解其原理和新技术,有助于进一步提升Java服务性能。
http://www.lryc.cn/news/533285.html

相关文章:

  • 使用 Ollama 在 Windows 环境部署 DeepSeek 大模型实战指南
  • 算法基础之八大排序
  • 使用TensorFlow和Keras构建卷积神经网络:图像分类实战指南
  • 音频进阶学习十一——离散傅里叶级数DFS
  • 20.<Spring图书管理系统①(登录+添加图书)>
  • 关于图像锐化的一份介绍
  • Django开发入门 – 0.Django基本介绍
  • 多智能体协作架构模式:驱动传统公司向AI智能公司转型
  • CentOS服务器部署Docker+Jenkins持续集成环境
  • 【prompt实战】AI +OCR技术结合ChatGPT能力项目实践(BOL提单识别提取专家)
  • 【Android】Android开发应用如何开启任务栏消息通知
  • 上传文件报错:the request was rejected because no multipart boundary was found
  • 大模型—Dify本地化部署实战
  • 功能架构元模型
  • 常用工具类——Collections集合框架
  • e2studio开发RA2E1(9)----定时器GPT配置输入捕获
  • 25/2/7 <机器人基础>雅可比矩阵计算 雅可比伪逆
  • 网络爬虫js逆向之异步栈跟栈案例
  • 使用Ollama本地部署deepseek
  • Rust错误处理:从灭火器到核按钮的生存指南
  • Golang:Go 1.23 版本新特性介绍
  • 电脑运行黑屏是什么原因?原因及解决方法
  • redis之AOF持久化过程
  • Elasticsearch:向量搜索的快速介绍
  • Docker在安装时遇到的问题(第一部分)
  • 使用 OpenGL ES 在 iOS 上渲染一个四边形:从基础到实现
  • Spring Boot 2 快速教程:WebFlux处理流程(五)
  • Vue 鼠标事件合集,关于鼠标右键的处理方法(改写鼠标右键方法、自定义鼠标右键)
  • 两种交换排序算法--冒泡,快速
  • 语音交友app系统源码功能及技术研发流程剖析