Mar*_*ger 30 java jit jvm jvm-hotspot
我已经使用过-XX:+PrintCompilation
,我知道JIT编译器的基本技术以及使用JIT编译的原因.
然而,我仍然没有发现JVM如何决定JIT编译方法,即"正确的时间来到JIT编译方法".
我是否正确地假设每个方法都开始被解释,并且只要它不被归类为"热方法"它就不会被编译?我有一些东西在脑后,我读到一个方法被认为是"热",当它执行至少10.000次(解释方法10.000次后,它将被编译),但我不得不承认我是不确定这个或我在哪里读到这个.
总结一下我的问题:
(1)只要没有将每种方法归类为"热"方法(并因此已被编译),或者即使它们不是"热门",也有理由编制方法?
(2)JVM如何将方法分为"非热"和"热"方法?执行次数?还要别的吗?
(3)如果"热"方法存在某些阈值(如执行次数),是否有Java标志(-XX:...
)来设置此阈值?
apa*_*gin 55
HotSpot编译策略相当复杂,特别是对于分层编译,它在Java 8中默认启用.它既不是一些执行,也不是CompileThreshold
参数问题.
可以在HotSpot源中找到最佳解释(显然,唯一合理的解释),请参阅advancedThresholdPolicy.hpp.
我将总结这个高级编译策略的要点:
i
;b
.后向分支通常表示代码中的循环.每次计数器达到某个频率值(TierXInvokeNotifyFreqLog
,TierXBackedgeNotifyFreqLog
)时,都会调用编译策略来决定当前运行的方法下一步该做什么.取决于的值i
,b
而C1和C2的编译器线程的当前负载,可以决定
这里的关键参数是TierXInvocationThreshold
和TierXBackEdgeThreshold
.可以根据编译队列的长度动态调整给定方法的阈值.
编译队列不是FIFO,而是优先级队列.
具有配置文件数据(第3层)的C1编译代码的行为类似,只是切换到下一级别(C2,第4层)的阈值要大得多.例如,在大约200次调用之后,可以在第3层编译解释的方法,而在5000次调用之后,C1编译的方法可以在第4层进行重新编译.
InlineFrequencyRatio
,InlineFrequencyCount
)时才能内联更大的方法.Pet*_*rey 10
控制它的主要参数是 -XX:CompileThreshold=10000
Java 8的Hotspot现在默认使用分层编译,使用从1级到4级的多个编译阶段.我相信1不是优化.级别3是C1(基于客户端客户端),级别4是C2(基于服务器编译器)
这意味着稍微优化可能比您预期的更早发生,并且在达到10K阈值后可以保持很长时间的优化.我见过的最高点是在一百万次调用后消除StringBuilder的转义分析.
注意:循环迭代多次可以触发编译器.例如,10K次的循环就足够了.
1)在方法被认为足够热之前,它被解释.但是,一些JVM(例如Azul Zing)可以在启动时编译方法,您可以强制Hotspot JVM通过内部API编译方法.Java 9也可能有一个AOT(Ahead Of Time)编译器,但它仍在研究AFAIK
2)呼叫次数或迭代次数.
3)是-XX:CompileThreshold=
主要的.