关于java:-XX:-TieredCompilation到底做什么?

What exactly does -XX:-TieredCompilation do?

使用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,或者根本不编译?


-XX:-TieredCompilation禁用中间编译层(1、2、3),以便在最大优化级别(C2)处解释或编译方法。

副作用TieredCompilation标志还更改了编译器线程数,编译策略和默认代码缓存大小。请注意,禁用TieredCompilation

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

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

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


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

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

Java 7附带的分层编译意味着热点编译器可以在这些步骤之间无缝切换。因此,发生的情况是,经过一定数量的运行后,将使用C1编译代码,然后再运行C2,则将对其进行编译。这是基于方法的,因此,当应用程序运行时,很大一部分将仅在解释器下运行(用于冷代码),然后在大量运行(热代码)后将其编译为表现更好。您可以通过运行来查看不同的级别

1
2
3
4
5
6
7
$ 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,则它将使用服务器VM(C2),否则将使用客户端VM(C1)。

因此-Xint将仅与解释器一起运行(即没有编译器),并且您可以分别选择仅使用-client-server的C1或C2以及-XX:-TieredCompilation


作为Java 8用户,建议禁用TieredComplilation以用于带浮点的生产环境。

Oracle不会在Java8上解决此问题。
所有带有G1GC的热点JVM 8都有相同的问题。

(错误1)(错误2)