2012-02-09 14 views
12

私たちのプロジェクトでは、いくつかのJavaバイトコード計測が行われます。そして、私たちはいくつかの奇妙な行動に遭遇しました。次のコードスニペットを仮定します。あなたが見ることができるように、Oracleのコンパイラが生成オラクルとEclipseのコンパイラで生成されるJavaバイトコードの相違

0: new #15; //class java/lang/Integer 
    3: iconst_2 
    4: invokespecial #17; //Method java/lang/Integer."<init>":(I)V 
    7: return 

:へ

0: new #2; //class java/lang/Integer 
    3: dup 
    4: iconst_2 
    5: invokespecial #3; //Method java/lang/Integer."<init>":(I)V 
    8: pop 
    9: return 

とEclipseのコンパイラ:

public void a() { 
    new Integer(2); 
    } 

Oracleのjavacは、次のバイトコードに上記のコンパイル"dup"は "new"の後にありますが、Eclipseはそうではありません。新しく作成されたIntegerインスタンスはまったく使用されていないため、このユースケースではまったく正しいので、 "dup"は必要ありません。

私の質問は以下のとおりです。

  1. 異なるコンパイラの違いの一部概要はありますか?記事/ブログ投稿ですか?
  2. "new"と "invokespecial"の間に "dup"がないと、初期化後にオブジェクトが使用されないと私は安全に結論できますか?
+4

バイトコードをインスツルメントすることであなたの目標は何ですか?この違いはあなたのために問題を引き起こしますか? Javaコンパイラがどのバイトコードを生成するかは保証されていません。将来のバージョンでは、Oracleのjavacで今見ているものとは異なるものが生成される可能性は十分にあるので、コンパイラによって生成された正確なバイトコードに大きく依存するプログラムを書くのは良い考えではありません。 – Jesper

+0

別のJDK for Eclipseを使用していますか? – Nishant

答えて

3
  1. 私は無事に「新しい」と「invokespecial」の間には「DUP」がない場合は、オブジェクトを初期化後に使用されていないことを、結論することはできますか?

は、私はあなたが正確にを何を意味するかわからないんだけど、作成されたオブジェクトへの参照は、コンストラクタでどこかに保存される可能性があります。したがって、呼び出し元のメソッドは初期化後にオブジェクトを使用しないかもしれませんが、オブジェクトはまだ到達可能であり、したがってガーベッジ・コレクタブルではない可能性があります。

6

DUP間の新しいinvokespecialがある場合、そのオブジェクトは、通常、コンパイル後に使用です。例えば、フィールドの初期化は、通常新しいDUPのシーケンスであり、invokespecial & をputfield。しかし、あなたの例では最後の指示はポップで、これはスタックからobjectrefを消去します。これは、このオブジェクトが使用されていないとみなす方法です。

+0

A.Hで指摘されているように、ポップは発信者が使用していないことを意味します。オブジェクトそのものは、ctor内の参照自体を与えることができます。 – Antimony

1

この参照は、このパターンビット

public class Bump { 

    Test t; 

    public Bump() { 
     new Test(this); 
    } 
    public void setT(Test t) { 
     this.t = t; 
    } 
    } 

を中断します。そして1は:)

public class Test { 

    Bump b; 

    public Test(Bump b) { 
     this.b = b; 
     b.setT(this); 
    } 
    } 

は楽しみを持って戻って結果を格納するためこのを使用することができます:)

を渡します
関連する問題