Подтвердить что ты не робот

Различия в java-байт-коде, создаваемые компиляторами Oracle и Eclipse

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

Мои вопросы:

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

Ответ 1

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

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

Ответ 2

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

Ответ 3

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

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

Удачи:)