12

私たちのプロジェクトは、いくつかの Java バイトコード インストルメンテーションを行います。そして、奇妙な行動に出くわしました。次のコード スニペットがあるとします。

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

Oracle の javac は、上記を次のバイトコードにコンパイルします。

   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のコンパイラを次のようにします:

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

ご覧のとおり、Oracle コンパイラは「new」の後に「dup」を生成しますが、Eclipse は生成しません。新しく作成された Integer インスタンスはまったく使用されないため、このユースケースではまったく正しいので、「複製」は必要ありません。

私の質問は次のとおりです。

  1. 異なるコンパイラ間の違いの概要はありますか? 記事/ブログ投稿?
  2. 「new」と「invokespecial」の間に「重複」がない場合、オブジェクトは初期化後に使用されないと安全に結論付けることができますか?
4

3 に答える 3

6

newinvokespecialの間に重複がある場合、オブジェクトは通常、コンパイル後に使用されます。たとえば、フィールドの初期化は通常、newdupinvokespecial & putfieldのシーケンスです。ただし、あなたの例では、最後の命令はスタックから objectref を消去するpopです。これは、このオブジェクトが使用されていないと想定できる方法です。

于 2012-02-09T08:19:55.957 に答える
3
  1. 「new」と「invokespecial」の間に「dup」がない場合、初期化後にオブジェクトは使用されないと安全に結論付けることができますか?

正確に何を意味するのかわかりませんが、作成されたオブジェクトへの参照は、コンストラクターによってどこかに格納されている可能性があります。したがって、呼び出し元のメソッドは初期化後にオブジェクトを使用しない可能性がありますが、オブジェクトは引き続き到達可能であり、したがってガベージ収集可能ではない可能性があります。

于 2012-02-09T08:37:29.493 に答える
1

この参照を渡すと、このパターンが少し壊れます

  public class Bump {

    Test t;

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

そして、これを使用して結果を保存することができます:)

  public class Test {

    Bump b;

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

楽しむ :)

于 2012-02-09T08:57:48.170 に答える