2016-11-08 8 views
7

私は同じクラスのインスタンスを2つ持っていますが、構築時に設定された最後のブール値フィールドに基づいて、異なるコードパスを使用して異なる動作をします。そう、何かのように:flagに異なる値を持つFooJVMは、同じクラスの異なるインスタンスを異なる方法で最適化できますか?

public class Foo { 
    private final boolean flag; 

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

    public void f() { 
     if (flag) { 
     doSomething(); 
     } else { 
     doSomethingElse(); 
     } 
    } 
} 

2のインスタンスは、理論的には、それによって、私はできれば(不自然な例のために申し訳ありませんが、その最も簡単な1のコストを排除し、2つの異なるアセンブリによってバックアップされる可能性が一緒に出てくる)。

私の質問です - どのJVMが実際にこれを行うのですか?または単一のアセンブリで常にサポートされている単一のクラスですか?

+1

あなたが説明していることは、サブクラス化に非常によく似ていると思われますが、それがうまくいかない理由を明確にすることはできますか?私は問題の境界を理解しようとするだけでは挑戦的ではありません。 – Taylor

+0

すべてのインスタンスが同じコードを共有します。あなたの質問は理にかなっていません。 – EJP

+2

@テイラー私はOPを解釈することを敢えてすればすみませますが、彼/彼女が求めているのは適切なパターン(明らかに継承)ではないと思いますが、JVMが " 'flag'変数を使用して、クラス全体の2つの異なるバイトコードを生成します(1つは' true'ブランチに対応し、もう1つは 'false'ブランチに対応します)。 –

答えて

7

はい、JVMはこの形式の最適化を行います。あなたの場合、これは常に真であるためにinlining and adaptive optimizationという結果になります。次のコードを考えてみましょう:

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

Fooは、単にメソッドのコードをコピー&ペーストするVMを可能にするものfの呼び出しサイトでFooの実際のインスタンスは、このように、常にあることHotSpotのために証明するのは簡単です仮想ディスパッチを排除します。インライン化した後、例がに縮小されています。最適化はそのための呼び出しサイトの単相性に依存しない適用することができた場合

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

:再び

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

これにコードを減らすことができますfooと安定性はflagです。 (VMは、このようなパターンのメソッドをプロファイリングします。)VMがプログラムの結果を予測することができないほど、最適化は適用されません。

の例では、上記のコードのようにとても些細だった場合、JITは、おそらくまた、オブジェクトの割り当てを消去し、単にdoSomethingを呼び出します。また、フィールドの値が簡単にtrueであることが判明している簡単な例の場合、VMは適応性を最適化する必要さえなく、単純に上記の最適化を適用します。 JITWatchという素晴らしいツールがあり、コードの最適化方法を調べることができます。

+2

この特定のケースでは、JVMはデータをプロファイリングせずに静的解析によって結果を生成することさえできます。結果は基本的には 'foo.flag = true;であるため、コンストラクタのコードをインライン展開した結果を示すことで、より直観的になります。 if(foo.flag)... '最適化するために' final'に 'flag'を必要としません。フォローアップコードによっては、この特定のコードパスの 'Foo'インスタンスも作成されません。 – Holger

5

次はホットスポットに適用され、他のJVMは異なる最適化を適用できます。

それらのインスタンスがでstatic finalフィールドに割り当てオンし、他のコードと、VMによって参照されている場合は、それらのインスタンスが一定の折りたたみに関与することができ、CONSTANT.f()をインライン化することは排除されて異なる分岐をもたらすことができる-XX:+TrustFinalNonStaticFieldsで開始されます。

sun.misc.Unsafe.defineAnonymousClass(Class<?>, byte[], Object[])を介してインスタンスの代わりに匿名クラスを作成し、各クラスのクラス定数にパッチを当てることもできますが、最終的には最適化に影響を与えるためにクラス定数によって参照する必要があります。

関連する問題