Skip to content
文章目录

1、字节码是如何运行的?

1.1、解释执行

  • 由解释器一行一行翻译执行

1.2、编译执行

  • 把字节码编译成机器码,直接执行机器码

1.3、解释vs编译

  • 解释执行

    • 优势在于没有编译的等待

    • 性能性对差一些

  • 编译执行

    • 运行效率会高很多,一般认为解释执行快一个数量级

    • 带来了额外的开销

2、查询运行模式

  • Java -version

33.png

我们发现他是混合模式

  • -Xint:

    • 设置JVM的执行模式为解释执行模式

34.png

  • Xcomp:

    • JVM优先以编译模式运行,不能编译的,以解释模式运行。

35.png

  • Xmixed:

    • 混合模式运行

3、运行过程

  • 一开始一般由解释器解释执行

  • 当虚拟机发现某个方法或代码块的运行特别频繁的时候,就会认为这些代码是"热点代码"。为了提高热点代码的执行效率,会用即时编译器(也就是JIT),把这些热点代码编译成与本地平台相关的机器码,并进行各层次的优化。

4、Hotstop的即时编译器

  • C1编译器(Client Compiler)

    • 是一个简单快速的编译器

    • 主要关注局部性的优化

    • 适用于执行时间较短或对启动性能有要求的程序。列如,GUI应用对界面启动速度就有一定要求。

  • C2编译器(Server Compiler)

    • 是为长期运行的服务器端应用程序做性能调优的编译器

    • 适用于执行时间较长或对峰值性能有要求的程序

5、分层编译

  • 0

    • 解释执行
  • 1

    • 简单C1编译:会用C1编译器进行一些简单的优化,不开启Profiling
  • 2

    • 受限的C1编译:仅执行带方法调用次数以及循环回边执行次数Profiling的C1编译
  • 3

    • 完全C1编译:会执行带有所有Profiling的C1代码
  • 4

    • C2编译:使用C2编译器执行优化,该级别会启用一些编译耗时较长的优化,一些情况下会根据性能监控信息进行一些非常激进的性能优化
  • 级别越高,应用启动越慢,优化的开销越高,峰值性能也越高。

注意:当开启分层编译时,JVM会根据当前待编译的方法数以及编译线程数来动态调整阈值,-XX:CompileThreshold,-XX:OnStackReplacePercentage都会失效。

6、如何找到热点代码?思路是?

6.1、基于采样的热点探测

  • 解释

采用这种方法的虚拟机会周期性地检查各个线程的栈顶,如果发现某些方法经常出现在栈顶,那这个方法就是“热点方法”。

  • 好处

    • 实现简单高效

    • 很容易地获取方法调用关系(将调用堆栈展开即可)

  • 缺点

    • 很难精确地确认一个方法的热度

    • 容易因为受到线程阻塞或别的外界因素的影响而扰乱热点探测

6.2、基于计数器的热点探测

6.2.1、方法调用计数器(Invocation Counter)

定义:

  • 用于统计方法被调用的次数,在不开启分层编译的情况下,在C1编译器下的默认阈值是1500次,在C2模式下是10 000次。也可用-XX:CompileThreshold=X指定阈值

执行流程:

36.png

特点:

如果不做任何设置,方法调用计数器统计的并不是方法被调用的绝对次数,而是一个相对的执行频率,即一段时间内方法被调用的次数,当超过一定的时间限度,如果方法的调用次数仍然不足以让它提交给即时编译器编译,那这个方法的调用计数器就会减少一半,这个过程被称为方法调用计数器热度的衰减,而这段时间就称为此方法统计的半衰周期。进行热度衰减的动作是在虚拟机进行垃圾收集时顺便进行的,可以使用虚拟机参数-XX:UseCounterDecay来关闭热度衰减,让方法计数器统计方法调用的绝对次数,这样,只要系统运行时间足够长,绝大部分方法都会被编译成本地代码,另外,可以使用-XX:CounterHalfLifeTime参数设置半衰周期的时间,单位是秒。

6.2.1、回边计数器(Back Edge Counter)

定义

  • 用于统计一个方法中循环体代码执行的次数,在字节码中遇到控制流向后跳转的指令称为"回边"(Back Edge)。在不开启分层编译的情况下,C1编译器下的默认阈值13995,C2默认为10700,可使用-XX:OnStackReplacePercentage=X指定阈值

  • 建立回边计算器的主要目的是为了触发OSR(On StackReplacement)编译

执行流程

37.png

7、配置参数

参数作用
-Xmixed混合模式运行(默认)
-Xint设置JVM的执行模式为解释执行模式
-XcompJVM优先一编译模式运行,不能编译的,以解释模式运行
-XX:-TieredCompilation禁止中间编译层
-XX:TieredStopAtLevel到哪个分层停止
-XX:CompileThreshold=X指定方法调用计数器阈值(关闭分层编译时才有效)
-XX:OnStackReplacePercentage=X指定回边计数器阈值(关闭分层编译时才有效)
-XX:-UseCounterDecay关闭方法调用计数器热度衰减
-XX:CounterHalfLifeTime指定方法调用计数器半衰周期(秒)