概述
是java虚拟机的核心组成成分之一。
“虚拟机”是一个相对于“物理机”的概念,区别在于物理机的执行引擎直接建立在处理器,缓存,指令集和操作系统层面上,虚拟机的执行引擎是由软件自行实现的。
在不同虚拟机实现中,执行引擎在执行字节码的时候,通常会有解释执行和编译执行两种选择,也可能两者兼备,还可能会同时包含几个不同级别的即时编译器一起工作的执行引擎。
JVM的主要任务是负责装载字节码到其内部,执行引擎的任务是将字节码指令解释/编译为对应平台上的本地机器指令才可以。
从外观上看,所有java虚拟机的执行引擎输入和输出一致的:输入的是字节码二进制流,处理过程是字节码解析执行的等效过程,输出的是执行结果。
工作过程
java代码编译和执行过程
java代码编译是由java源码编译器来完成,流程图如下
java字节码的执行是由JVM执行引擎来完成,流程图如下
解释器
解释器:将字节码文件中的内容“翻译”为对应平台的本地机器指令执行
JIT编译器
HotSpot JVM的执行方式
目前主流的商用java虚拟机,内部同时包含解释器和编译器。
当程序需要快速启动和执行的时候,解释器首先发挥作用,省去编译时间,立即执行。当程序启动后,编译器逐渐发挥作用,把代码编译成本地代码,减少解释器的中间损耗。当内存资源限制大,使用解释执行节约内存,反之使用编译执行提高效率。
解释器还可以作为编译器的“逃生门”。
热点代码
热点代码:当虚拟机发现某个方法或者代码块的运行特别频繁
为了提高热点代码的执行效率,在运行时,虚拟机将会把这些代码编译成本地机器码,并以各种手段尽可能地进行代码优化。
在运行过程中会被即时编译器编译的目标是“热点代码“,主要有两类:被多次调用的方法,被多次执行的循环体。
热点探测
基于采样的热点探测
基于采样的热点探测:虚拟机会周期性地检查各个线程的调用栈顶,如果发现某个方法经常出现在栈顶,那这个方法就是“热点方法”。
好处:实现简单高效,很容易地获取方法调用关系。
缺点:很难精确地确定一个方法的热度,容易因为受到线程阻塞或别的外界因素的影响而扰乱热点探测。
基于计数器的热点探测
基于计数器的热点探测:虚拟机会为每个方法(甚至是代码块)建立计数器,统计方法的执行次数,如果执行次数超过一定阈值就认为它是“热点方法”。需要麻烦一些,且无法直接获取方法调用关系统计,但结果相对准确。
方法调用计数器
默认阈值:客户端1500,服务器:10000
-XX:ComplieThreshold设计阈值
当一个方法被调用时,会先检查该方法是否存在被 JIT 编译过的版本,如果存在,则优先使用编译后的本地代码来执行。如果不存在已被编译过的版本,则将此方法的调用计数器值加 1,然后判断方法调用计数器与回边计数器值之和是否超过方法调用计数器的阈值。如果已超过阈值,那么将会向即时编译器提交一个该方法的代码编译请求。
如果不做任何设置,方法调用计数器统计的并不是方法被调用的绝对次数,而是一个相对的执行频率,即一段时间之内方法被调用的次数。当超过一定的时间限度,如果方法的调用次数仍然不足以让它提交给即时编译器编译,那这个方法的调用计数器就会被减少一半,这个过程称为方法调用计数器热度的衰减(Counter Decay),而这段时间就称为此方法统计的半衰周期(Counter Half Life Time)。
进行热度衰减的动作是在虚拟机进行垃圾收集时顺便进行的,可以使用虚拟机参数-XX:-UseCounterDecay来关闭热度衰减,让方法计数器统计方法调用的绝对次数,这样,只要系统运行时间足够长,绝大部分方法都会被编译成本地代码。
另外,可以使用 -Xx:CounterHalfLifeTime参数设置半衰周期的时间,单位是秒。
回边计数器
它的作用是统计一个方法中循环体代码执行的次数,在字节码中遇到控制流向后跳转的指令称为 “回边”(Back Edge)。显然,建立回边计数器统计的目的就是为了触发OSR编译。
概述
是java虚拟机的核心组成成分之一。
“虚拟机”是一个相对于“物理机”的概念,区别在于物理机的执行引擎直接建立在处理器,缓存,指令集和操作系统层面上,虚拟机的执行引擎是由软件自行实现的。
在不同虚拟机实现中,执行引擎在执行字节码的时候,通常会有解释执行和编译执行两种选择,也可能两者兼备,还可能会同时包含几个不同级别的即时编译器一起工作的执行引擎。
JVM的主要任务是负责装载字节码到其内部,执行引擎的任务是将字节码指令解释/编译为对应平台上的本地机器指令才可以。
从外观上看,所有java虚拟机的执行引擎输入和输出一致的:输入的是字节码二进制流,处理过程是字节码解析执行的等效过程,输出的是执行结果。
工作过程
java代码编译和执行过程
java代码编译是由java源码编译器来完成,流程图如下
java字节码的执行是由JVM执行引擎来完成,流程图如下
解释器
解释器:将字节码文件中的内容“翻译”为对应平台的本地机器指令执行
JIT编译器
HotSpot JVM的执行方式
目前主流的商用java虚拟机,内部同时包含解释器和编译器。
当程序需要快速启动和执行的时候,解释器首先发挥作用,省去编译时间,立即执行。当程序启动后,编译器逐渐发挥作用,把代码编译成本地代码,减少解释器的中间损耗。当内存资源限制大,使用解释执行节约内存,反之使用编译执行提高效率。
解释器还可以作为编译器的“逃生门”。
热点代码
热点代码:当虚拟机发现某个方法或者代码块的运行特别频繁
为了提高热点代码的执行效率,在运行时,虚拟机将会把这些代码编译成本地机器码,并以各种手段尽可能地进行代码优化。
在运行过程中会被即时编译器编译的目标是“热点代码“,主要有两类:被多次调用的方法,被多次执行的循环体。
热点探测
基于采样的热点探测
基于采样的热点探测:虚拟机会周期性地检查各个线程的调用栈顶,如果发现某个方法经常出现在栈顶,那这个方法就是“热点方法”。
好处:实现简单高效,很容易地获取方法调用关系。
缺点:很难精确地确定一个方法的热度,容易因为受到线程阻塞或别的外界因素的影响而扰乱热点探测。
基于计数器的热点探测
基于计数器的热点探测:虚拟机会为每个方法(甚至是代码块)建立计数器,统计方法的执行次数,如果执行次数超过一定阈值就认为它是“热点方法”。需要麻烦一些,且无法直接获取方法调用关系统计,但结果相对准确。
方法调用计数器
默认阈值:客户端1500,服务器:10000
-XX:ComplieThreshold设计阈值
当一个方法被调用时,会先检查该方法是否存在被 JIT 编译过的版本,如果存在,则优先使用编译后的本地代码来执行。如果不存在已被编译过的版本,则将此方法的调用计数器值加 1,然后判断方法调用计数器与回边计数器值之和是否超过方法调用计数器的阈值。如果已超过阈值,那么将会向即时编译器提交一个该方法的代码编译请求。
如果不做任何设置,方法调用计数器统计的并不是方法被调用的绝对次数,而是一个相对的执行频率,即一段时间之内方法被调用的次数。当超过一定的时间限度,如果方法的调用次数仍然不足以让它提交给即时编译器编译,那这个方法的调用计数器就会被减少一半,这个过程称为方法调用计数器热度的衰减(Counter Decay),而这段时间就称为此方法统计的半衰周期(Counter Half Life Time)。
进行热度衰减的动作是在虚拟机进行垃圾收集时顺便进行的,可以使用虚拟机参数-XX:-UseCounterDecay来关闭热度衰减,让方法计数器统计方法调用的绝对次数,这样,只要系统运行时间足够长,绝大部分方法都会被编译成本地代码。
另外,可以使用 -Xx:CounterHalfLifeTime参数设置半衰周期的时间,单位是秒。
回边计数器
它的作用是统计一个方法中循环体代码执行的次数,在字节码中遇到控制流向后跳转的指令称为 “回边”(Back Edge)。显然,建立回边计数器统计的目的就是为了触发OSR编译。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/bian-cheng-ri-ji/6480.html