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

时间:2016-11-08 18:22:40

标签: 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();
      }
   }
}

Foo flag的两个{{1}}个实例理论上可以由两个不同的程序集支持,从而消除了if的成本(对于人为的例子,对不起,这是我能做的最简单的例子)想出来。)

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

2 个答案:

答案 0 :(得分:7)

是的,JVM采用这种形式的优化。在您的情况下,这将是inlining and adaptive optimization的结果,因为它是一个永远为真的值。请考虑以下代码:

Foo foo = new Foo(true);
foo.f();

为HotSpot证明Foo始终是Foo的调用网站上的f的实际实例,这是微不足道的,因为它允许VM简单地复制粘贴代码方法,从而消除了虚拟调度。内联后,示例简化为:

Foo foo = new Foo(true);
if (foo.flag) {
  doSomething();
} else {
  doSomethingElse();
}

这又允许将代码缩减为:

Foo foo = new Foo(true);
foo.doSomething();

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

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

答案 1 :(得分:5)

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

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

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