Java JVM是如何决定JIT编译一个方法的(将一个方法归类为“hot”的)?

Java JVM是如何决定JIT编译一个方法的(将一个方法归类为“hot”的)?,java,jvm,jit,jvm-hotspot,Java,Jvm,Jit,Jvm Hotspot,我已经使用过-XX:+printcomployment,我知道JIT编译器的基本技术以及使用JIT编译的原因 然而,我仍然没有发现JVM是如何决定JIT编译一个方法的,也就是“何时到了JIT编译方法的适当时机” 我是否正确地假设每个方法都开始被解释,并且只要它没有被归类为“热方法”,它就不会被编译?在我的脑海里,我读到一个方法被执行至少10.000次时被认为是“热的”(在解释了10.000次方法之后,它将被编译),但我不得不承认,我不确定这一点或者我在哪里读到过这一点 因此,总结我的问题: (1

我已经使用过
-XX:+printcomployment
,我知道JIT编译器的基本技术以及使用JIT编译的原因

然而,我仍然没有发现JVM是如何决定JIT编译一个方法的,也就是“何时到了JIT编译方法的适当时机”

我是否正确地假设每个方法都开始被解释,并且只要它没有被归类为“热方法”,它就不会被编译?在我的脑海里,我读到一个方法被执行至少10.000次时被认为是“热的”(在解释了10.000次方法之后,它将被编译),但我不得不承认,我不确定这一点或者我在哪里读到过这一点

因此,总结我的问题:

(1) 是否每个方法都被解释为只要它没有被归类为“热”方法(并因此被编译),或者即使它们不是“热”方法,也有理由被编译

(2) JVM如何将方法分为“非热”和“热”方法?执行次数?还有别的吗


(3) 如果“热”方法有某些阈值(如执行次数),是否有Java标志(
-XX:…
)来设置此阈值?

控制此阈值的主要参数是
-XX:CompileThreshold=10000

Hotspot for Java 8现在默认使用分层编译,使用从级别1到级别4的多个编译阶段。我认为1不是优化。级别3是C1(基于客户端),级别4是C2(基于服务器编译器)

这意味着可以比您预期的更早进行一点优化,并且在达到10K阈值后可以保持很长时间的优化。我所见过的最高级别是在一百万次调用后消除StringBuilder的escape分析

注意:循环多次迭代可能会触发编译器。e、 g.一个10K次的回路就足够了

1) 直到一种方法被认为足够热,它才会被解释。但是,一些JVM(例如Azul Zing)可以在启动时编译方法,您可以强制Hotspot JVM通过内部API编译方法。Java9也可能有一个AOT(提前)编译器,但它仍在研究中

2) 调用数或迭代次数


3) 是
-XX:CompileThreshold=
是主要的编译策略。

热点编译策略相当复杂,尤其是对于分层编译,在Java 8中默认情况下是打开的。这既不是执行的次数,也不是
CompileThreshold
参数的问题

最好的解释(显然,唯一合理的解释)可以在热点来源中找到,请参阅

我将总结此高级编译策略的要点:

  • 执行从第0层(解释器)开始
  • 编译的主要触发器有
  • 方法调用计数器
    i
  • 后缘计数器
    b
    。向后分支通常表示代码中的循环
  • 每当计数器达到某个频率值(
    TierXInvokeNotifyFreqLog
    TierXBackedgeNotifyFreqLog
    ),就会调用一个编译策略来决定下一步如何处理当前运行的方法。根据
    i
    b
    的值以及C1和C2编译器线程的当前负载,可以决定

    • 继续在解释器中执行
    • 在解释器中启动评测
    • 在第3层使用C1编译方法,并提供进一步重新编译所需的完整剖面数据
    • 在第2层使用C1编译方法,没有配置文件,但有可能重新编译(不太可能)
    • 最后在第1层用C1编译方法,没有配置文件或计数器(也不太可能)
    这里的关键参数是
    tierxinocationthreshold
    TierXBackEdgeThreshold
    。可以根据编译队列的长度动态调整给定方法的阈值

  • 编译队列不是FIFO,而是优先级队列

  • 带有概要文件数据的C1编译代码(第3层)的行为类似,只是切换到下一层(C2,第4层)的阈值要大得多。例如,一个解释方法可以在大约200次调用后在第3层编译,而C1编译方法在5000多次调用后在第4层重新编译

  • 方法内联使用特殊策略。微小的方法可以内联到调用程序中,即使它们不是“热的”。仅当频繁调用较大的方法时(
    InlineFrequencyRatio
    InlineFrequencyCount

您是否有其他资料可供我阅读?我知道C1和C2,但我还没有听说过编译级别1-4(Interpeter、C1、C2将是3个级别)。而且,您基本上会说,在
编译器阈值以下的方法可能会被认为是热门的。那么这个门槛是什么呢?当一个方法被调用
CompilerThreshold
次时,我是否可以排除它被认为是热的?很抱歉接下来的问题,但只是为了让我的术语正确:如果一个方法至少被优化过一次,我是否可以将它称为“热的”,或者这正是“热方法”的定义?@MarkusWeninger这是一个不断更新的东西。如果多次调用同一组代码(但每次调用一次),您可以看到它们并不是一次编译完成的。实际的算法要复杂得多。我认为,获取更多信息的最佳场所是信息源。对于当前JVM,任何其他编写的内容都可能过时。@MarkusWeninger编译是在后台完成的,如果有很多方法可以编译,那么这可能会花费大量的时间。当一个方法成为编译的候选对象时,我会说它是“热门”的。当它被编译并替换现有代码时