运行期优化

简介:

一、概述

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

二、HotSpot虚拟机内的即时编译器

1、解释器与编译器

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

HotSpot虚拟机中内置两个即时编译器,分别称为Client Compiler 和Server Compiler,简称C1编译器和C2编译器。
默认C1编译器,可以使用-client 或 -server 指定。
解释器与编译器搭配使用的方式在虚拟机中称为混合模式,用户可以通过参数-Xint强制虚拟机运行与解释模式(Interpreted Mode),
这时编译器完全不参与工作,全部代码都使用解释方式执行。
也可以使用-Xcomp强制虚拟机运行编译模式(Compiled Mode),这时将优先采用编译方式执行程序。
Client Compiler 可以获得更高的编译速度,Server Compiler可以获得更好的编译质量。

2、编译对象与触发条件u

热点代码:

  • 被多次调用的方法
  • 被多次执行的循环体

    判断一段代码是不是热点代码,是不是需要触发即时编译,这样的行为称为热点探测。热点探测方式:

  • 基于采样的热点探测:虚拟机周期性的检查各个线程的栈顶,如果发现某个方法经常出现在栈顶,那这个方法就是热点方法。
  • 基于计数器的热点探测:虚拟机为每个方法建立计数器,统计方法的执行次数,如果执行次数超过一定阈值,就认为是热点方法。
    HotSpot采样的是基于计数器的热点探测,为每个方法准备两类计数器:方法调用计数器、回边计数器。

方法调用计数器:统计方法被调用的次数,Client模式下默认1500次,Server模式下默认10000次,可以通过虚拟机参数-XX:CompiledThreshold修改。
回边计数器:统计一个方法中循环体代码执行次数。

三、编译优化技术

1、公共子表达式消除

如果一个表达式E已经计算过了,并且从先前的计算到现在E中所有的变量的值都没有发生变化,那么E的这次出现就成为了公共子表达式。
对于这种表达式就没有必要花时间对它进行计算,只需直接用前面计算过的表达式结果代替E就可以了。

    
    int d = (c * b) * 12 + a + (a + b * c);
    
    int d = E * 12 + a + (a + E);
AI 代码解读

当这段代码进入虚拟机即时编译器编译后,就变为了第二行代码

2、数组边界检查消除

java 在访问数组类型数据时会自动进行上下界范围检查,如果超出范围将抛出ArrayIndexOutOfBoundsException,每次数据读写都带有一次
隐含的条件判定,影响性能。对于循环体来说,如果编译器可以判定循环变量取值范围永远在[0,length())之间,那在整个循环中就可以
把数组上下界检查消除。

3、方法内联

把目标的代码复制到发起调用的方法中,避免发生真实的方法调用。
分析对象动态作用域:当一个对象在方法中被定义后,它可能被外部方法所引用,例如作为调用参数传递到其他方法中,称为方法逃逸。
甚至可能被外部线程访问到,譬如赋值给类变量或可以在其他线程中访问的实例变量,称为线程逃逸。
如果能证明一个对象不会逃逸到变量或线程外,也就是别的方法或线程无法通过任何途径访问到这个对象,则可能为为这个变量进行优化。

  • 栈上分配:java虚拟机中,在java堆上分配创建对象的内存空间,java堆中的对象对于各个线程都是共享可见的,只要持有这个对象的引用,
    就可以访问堆中存储的对象数据。虚拟机垃圾收集系统可以回收堆中不再使用的对象。

如果确定一个对象不会逃逸出方法之外,那让这个对象在栈上分配,对象占用的内存就可以随栈帧出栈而销毁。

  • 同步消除:线程同步本身就是一个相对耗时的过程,如果逃逸分析能够确定一个变量不会逃逸出线程,无法被其他线程访问,那这个变量的读写
    肯定就不会有竞争,对这个变身实施同步措施也就可以消除。
  • 标量替换:标量是指一个数据已经无法分解成更小的数据来表示,Java虚拟机中的原始数据类型都不能再进一步分解,就可以称为标量。
    相对的,如果一个数据可以继续分解,称为聚合量,java中的对象就是典型的聚合量。如果把一个Java对象拆散,根据程序访问的情况,将其使用

到的成员变量恢复原始类型来访问就叫标量替换。如果逃逸分析证明一个对象不会被外部访问,并且对象可以被拆散的话, 程序真正执行的时候
可能不创建这个对象,而改为直接创建它的若干被这个方法使用到的成员变量替换。这些变量建立在栈上分配读写。

目录
打赏
0
0
0
0
8
分享
相关文章
【初阶C语言】学会使用库函数getchar和putchar
【初阶C语言】学会使用库函数getchar和putchar getchar函数 该函数的作用是接收一个字符,然后把该字符转化对应的ASCII值
635 0
《AI与NLP:开启元宇宙社交互动新纪元》
元宇宙正从概念走向现实,社交互动成为其核心魅力。AI与NLP技术的迅猛发展,使自然语言交互、个性化体验和情感交流成为可能,打破了沟通壁垒,满足多元需求,并赋予社交温度。实时翻译技术支持跨语言交流,构建全球社交网络。尽管仍面临挑战,未来前景广阔,将带来更加真实、高效的虚拟社交体验。
132 6
无人出租车是一种利用人工智能、传感器、激光雷达等技术实现自动驾驶的交通工具
无人出租车是一种利用人工智能、传感器、激光雷达等技术实现自动驾驶的交通工具
无人出租车是一种利用人工智能、传感器、激光雷达等技术实现自动驾驶的交通工具
|
11月前
|
数字化转型障碍克服问题之下一代大型机人才的培养如何解决
数字化转型障碍克服问题之下一代大型机人才的培养如何解决
77 4
Qt定义属性类信息报错‘Qstring‘ was not declared in this scope; did you mean ‘xxx‘?并且还有有一堆报错,问题还出现在moc文件
Qt定义属性类信息报错‘Qstring‘ was not declared in this scope; did you mean ‘xxx‘?并且还有有一堆报错,问题还出现在moc文件
246 0
SpringBoot-22-RESTful统一规范响应数据格式
REST是Representational State Transfer的缩写,是在2000年被Roy Thomas Fielding提出的,Fielding是一个很厉害的人物,他是HTTP协议的主要设计者。REST是他对互联网软件构架的原则。REST是一种针对网络应用设计和软件开发方式,降低了开发的复杂性,提高了系统的可伸缩性。如果想要具体了解一下其含义可以查看一下阮一峰老师对REST理解RESTful架构。
221 0
【算法】11. 盛最多水的容器(多语言实现)
给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。 找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。 返回容器可以储存的最大水量。 说明: 你不能倾斜容器。
【算法】11. 盛最多水的容器(多语言实现)
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等