“-XX:-TieredCompilation” 的作用是什么?

83

使用java -XX:+PrintFlagsFinal,我找到了TieredCompilation标志,并在网上阅读了一些相关内容。

然而,我仍然不知道将其设置为false时会发生什么。

我知道编译系统支持5个执行级别,基本上分为解释器、C1和C2:

  • 级别0-解释器
  • 级别1-C1具有完全优化(无剖析)
  • 级别2-C1具有调用和回边计数器
  • 级别3-C1具有完整剖析(级别2+MDO)
  • 级别4-C2

来源: http://hg.openjdk.java.net/jdk8u/jdk8u/hotspot/file/2b2511bd3cc8/src/share/vm/runtime/advancedThresholdPolicy.hpp#l34

两个问题:

(1) 通过设置-XX:-TieredCompilation,是否有一些级别被禁用了?如果是,那么是哪些级别?

(2) 是否有一些标志可以决定是否禁用C1或C2,或者根本不编译?

3个回答

93

-XX:-TieredCompilation 禁用所有中间编译层(1、2、3),这样一个方法要么被解释执行,要么以最大优化级别(C2)编译执行。

当禁用 TieredCompilation 标志时,会产生以下副作用:

  • 编译器线程数量减少;
  • 选择简单的编译策略(基于方法调用和回边计数器),而不是高级的编译策略
  • 默认保留的代码缓存大小会缩小5倍

要禁用 C2 编译器并仅使用没有额外开销的 C1,请设置 -XX:TieredStopAtLevel=1

要禁用所有 JIT 编译器并在解释器中运行所有内容,请使用 -Xint


谢谢!现在我有些困惑,因为我得到了不同的答案:设置 -XX:-TieredCompilation 现在会(1.)禁用 C1 并始终编译到最大值(C2),还是(2.)根据 CPU 启发式地决定禁用哪个编译层次(如 @AlBlue 所述)?这也使我难以决定哪一个答案是正确的 :P - Markus Weninger
@ MarkusWeninger 我已在 AlBlue 的答案下发表了评论。它不是很准确。 - apangin
谢谢,我刚看到。在第二条评论中,您提到了“TierXCompileThreshold”和“-XX:CompilationPolicyChoice = 2”,这是两个我仍然不了解的新东西,但我会去了解一下。: P 但第一条评论很好地回答了我的问题。 - Markus Weninger

28

有不同级别的JIT,正如您所注意到的(包括完全不运行JIT)。

在旧版本的Java中,您必须首先选择它们(例如-Xint-client-server)才能仅使用解释器、仅使用客户端(C1)编译器或仅使用服务器(C2)编译器运行。

Tiered compilation是Java 7中引入的,这意味着hotspot编译器可以在这些步骤之间无缝切换。因此,发生的情况是,在一定数量的运行之后,代码将使用C1进行编译,然后在更多的运行之后,它将使用C2进行编译。这是基于方法的,因此当应用程序运行时,重要的部分将只在解释器下运行(用于冷代码),然后在运行了大量代码后(热点),它将被编译为更高效的代码。您可以通过运行来查看不同的级别

$ java -XX:+PrintFlagsFinal -version | grep CompileThreshold
intx Tier2CompileThreshold                     = 0
intx Tier3CompileThreshold                     = 2000
intx Tier4CompileThreshold                     = 15000
openjdk version "1.8.0_92"
OpenJDK Runtime Environment (Zulu 8.15.0.1-macosx) (build 1.8.0_92-b15)
OpenJDK 64-Bit Server VM (Zulu 8.15.0.1-macosx) (build 25.92-b15, mixed mode)

-XX:-TieredCompilation实际上就是TieredCompilation=false,这意味着不进行此转换,并且您必须事先选择使用客户端或服务器编译器。JVM会根据您的CPU启发式地决定应用哪种模式;如果您有多个处理器或64位VM,则它将使用Server VM(C2),否则将使用Client VM(C1)。

因此,-Xint将仅使用解释器运行(即无编译器),您可以分别使用-client-server选择仅使用C1或C2,以及-XX:-TieredCompilation


1
谢谢,-Xint-client-server 就是我一直在寻找的标志。 - Markus Weninger
2
如果你想更深入地了解编译级别,可以参考我在 https://speakerdeck.com/alblue/hotspot-under-the-hood 中的介绍。 - AlBlue
谢谢,我会看一下的! :) - Markus Weninger
17
在现代JDK版本中,-client-server标志已被忽略。使用-XX:-TieredCompilation-XX:TieredStopAtLevel = 1来禁用C1或C2。请注意,这不会改变原始含义。 - apangin
5
除非使用 -XX:CompilationPolicyChoice=2 明确选择了 SimpleThresholdPolicy,否则 TierXCompileThreshold 标志在分层编译中不起作用。 - apangin

5
作为Java 8用户,建议在浮点数的生产环境中禁用TieredComplilation。
Oracle不会在Java8上修复此问题。 所有使用G1GC的热点JVM 8都有相同的问题。
Bug1)(Bug2

7
自Java 9起,错误已经被修复。 - Desik
如何禁用分层编译?使用-XX:-TieredCompilation。在浮点数中使用什么? - Lonzak
4
这些漏洞在8u192和8u201中得到修复,因此现在可以安全地在Java 8中使用。 - AlBlue

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接