moderm JVM可以不同地优化同一类的不同实例吗?

rad*_*dai 8 java optimization jvm bytecode jvm-hotspot

假设我有2个相同类的实例,但它们的行为不同(遵循不同的代码路径)基于构造时设置的最终布尔字段.像这样的东西:

public class Foo {
   private final boolean flag;

   public Foo(boolean flagValue) {
      this.flag = flagValue;
   }

   public void f() {
      if (flag) {
         doSomething();
      } else {
         doSomethingElse();
      }
   }
}
Run Code Online (Sandbox Code Playgroud)

理论上,2个Foo具有不同值的实例flag可以由2个不同的程序集支持,从而消除了if的成本(对于人为的例子,这是我能想到的最简单的例子).

所以我的问题是 - 任何JVM实际上都这样做吗?或者是一个总是由单个程序集支持的单个类?

Raf*_*ter 7

是的,JVM采用这种形式的优化.在您的情况下,这将是内联和自适应优化的结果,因为值始终为真.请考虑以下代码:

Foo foo = new Foo(true);
foo.f();
Run Code Online (Sandbox Code Playgroud)

为HotSpot证明Foo始终是Foo调用站点的实际实例是很f简单的,因为VM允许VM简单地复制粘贴方法的代码,从而消除虚拟调度.内联后,示例简化为:

Foo foo = new Foo(true);
if (foo.flag) {
  doSomething();
} else {
  doSomethingElse();
}
Run Code Online (Sandbox Code Playgroud)

这再次允许将代码减少到:

Foo foo = new Foo(true);
foo.doSomething();
Run Code Online (Sandbox Code Playgroud)

如果可以应用优化,则取决于foo的调用站点的单态性和该调用站点的稳定性flag.(VM会为您提供此类模式的方法.)VM能够预测程序结果的次数越少,优化的应用就越少.

如果该示例与上面的代码一样微不足道,那么JIT可能也会擦除对象分配并简单地调用doSomething.此外,对于可以证明该字段的值非常简单的简单示例情况true,VM甚至不需要自适应地优化,而是简单地应用上述优化.有一个名为JITWatch的强大工具,可以让您了解代码的优化方式.

  • 在这种特定情况下,JVM甚至可以通过静态分析生成结果,而无需分析数据.通过显示内联构造函数代码的结果,它会变得更直观,因为结果基本上是`foo.flag = true; if(foo.flag)...`甚至不需要`flag`来'final`来优化.根据后续代码,它甚至不会为此特定代码路径创建`Foo`实例. (2认同)

the*_*472 5

以下内容适用于热点,其他JVM可能会应用不同的优化.

如果这些实例被转换为static final字段然后由其他代码引用并且VM启动,-XX:+TrustFinalNonStaticFields那么这些实例可以参与常量折叠并且内联CONSTANT.f()可以导致消除不同的分支.

特权代码可用的另一种方法是创建匿名类而不是实例,sun.misc.Unsafe.defineAnonymousClass(Class<?>, byte[], Object[])并为每个类修补类常量,但最终还必须通过类常量引用以对优化产生任何影响.