反优化


当查看-XX:+PrintCompilationJVM标志,很容易发现一些条目带有“made not entrant”和“made zombie”,这表示所谓的去优化。它的基本意思是,先前编译的代码必须退出。

非进入者代码

在以下方案中,可以使代码不进入:

  • 当使用多态时。
  • 在分层编译期间。

多态性

我们来看一个例子:

Parser parser;

if (document.isLong()) {
  parser = new RemoteParser();
} else {
  parser = new LocalParser();
}

String parsedDocument = parser.parse(document);
// ...

正如您所看到的,解析器的实现取决于文档的长度。如果要解析长文档,我们将使用RemoteParser,否则将是LocalParser。让我们想象一下下面的情况:有海量的长文档需要解析;JIT编译器将注意到解析器的实际类型是RemoteParser。它将使用内联parse方法(if applicable),并执行进一步的优化,假设解析器的类型始终是RemoteParser

现在,让我们用海量的短文档调用上面的代码。关于解析器类型的假设不再有效,因此之前应用的优化也是无效的。这意味着已编译的方法被设置为不可入的。JVM将放弃所有这些优化,并开始用LocalParser

分层编译

由于…的性质Tiered Compilation,当使用不同的编译级别编译该方法时,使用前一级别编译的代码将被设置为不可进入的。它的基本意思是,在新级别上的编译是从头开始的(然而,它可以使用已经收集的概要文件数据)。

僵尸代码

编译日志中的“僵尸代码”指的是以前不进入的代码已经被回收。换句话说,以前使用优化的所有对象都不存在了,因此优化后的代码可以从代码缓存中删除(编译后的代码保存在缓存中,当然,缓存是有限的)。