Различия в байт-коде Java, создаваемом компиляторами Oracle и Eclipse - PullRequest
12 голосов
/ 09 февраля 2012

Наш проект выполняет инструментарий Java для байт-кода. И мы наткнулись на какое-то странное поведение. Предположим, следующий фрагмент кода:

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

Javac от Oracle компилирует вышеперечисленное в следующий байт-код:

   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 выдает «dup» после «new», а Eclipse - нет. Что совершенно правильно в этом случае использования, поскольку вновь созданный экземпляр Integer вообще не используется, поэтому «dup» не требуется.

Мои вопросы:

  1. Есть ли какой-то обзор различий между разными компиляторами? Статья / сообщение в блоге?
  2. Можно ли с уверенностью заключить, что если между "new" и "invokespecial" нет "dup", то объект не используется после инициализации?

Ответы [ 3 ]

6 голосов
/ 09 февраля 2012

Если есть dup между new и invokespecial , тогда объект обычно используется после компиляции. Например, инициализация поля обычно представляет собой последовательность new , dup , invokespecial & putfield . Однако в вашем примере последняя инструкция - pop , которая очищает objectref из стека - это то, как вы можете предположить, что этот объект не используется.

3 голосов
/ 09 февраля 2012
  1. Можно ли с уверенностью заключить, что если между "new" и "invokespecial" нет "dup", то объект не используется после инициализации?

Я не уверен, что вы имеете в виду точно , но ссылка на созданный объект может быть сохранена где-то конструктором.Поэтому вызывающий метод может не использовать объект после инициализации, но объект все еще может быть достижимым и, следовательно, не может быть сборщиком мусора.

1 голос
/ 09 февраля 2012

Передача эта ссылка немного нарушит этот шаблон

  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);
    }
  }

Веселитесь:)

...