Являются подконтексты в Java отдельными строками на стеке?

В Java дело обстоит так:

public void method() {
  if (condition) {
    Object x = ....;
  }
  System.out.println(x); // Error: x unavailable
}

То, что я задаюсь вопросом, является этим: факт это x ограничен объемом if- оператор просто функция компилятора Java, или x на самом деле удаленный из стека после if- оператор?

7
задан Bart van Heukelom 17 June 2010 в 11:24
поделиться

4 ответа

Нет, блоки кода не получить отдельный фрейм стека, используйте один из окружающих методов.

Однако, как только переменная покидает область видимости, ее место в текущем кадре стека может быть повторно использовано для других переменных.

Структура и использование кадра стека описаны в Спецификация виртуальной машины Java § 3.6 Кадры :

Новый кадр создается каждый раз, когда вызывается метод. Кадр уничтожается, когда завершается вызов его метода, независимо от того, является ли это завершение нормальным или внезапным (он вызывает неперехваченное исключение).

Это определенно определяет соотношение 1: 1 между вызовами методов и фреймами.

7
ответ дан 7 December 2019 в 03:11
поделиться

Блоки являются частью языка Java (который является языком структурированного программирования ), в то время как они не являются частью скомпилированного байт-кода (который является неструктурированным языком ).

Спецификация метода в файле класса определяет, сколько локальных переменных использует метод в целом, над фактическим списком инструкций. Но где блоки когда-то, где в коде Java, не могут быть выведены из байт-кода.

2
ответ дан 7 December 2019 в 03:11
поделиться

Да, он действительно удаляется из стека, делая слот, ранее занимаемый 'x', повторно используемым какой-либо другой локальной переменной.

-1
ответ дан 7 December 2019 в 03:11
поделиться

Прежде всего, в байт-коде переменные хранятся в слотах переменных и слотах переменных, а не в стеке. Слот может быть повторно использован другой переменной, но не гарантируется, что значение будет удалено из слота переменной.

Например, следующий класс

  public class A {
    public void method(boolean condition) {
 6    if (condition) {
 7      Object x = "";
 8      System.out.println(x);
 9    }
10    System.out.println(condition);
    }
  }

компилируется в этот байт-код:

// class version 50.0 (50)
public class A {
  ...

  // access flags 0x1
  public method(Z)V
   L0
    LINENUMBER 6 L0
    ILOAD 1
    IFEQ L1
   L2
    LINENUMBER 7 L2
    LDC ""
    ASTORE 2
   L3
    LINENUMBER 8 L3
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
    ALOAD 2
    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/Object;)V
   L1
    LINENUMBER 10 L1
   FRAME SAME
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
    ILOAD 1
    INVOKEVIRTUAL java/io/PrintStream.println (Z)V
   L4
    LINENUMBER 11 L4
    RETURN
   L5
    LOCALVARIABLE this LA; L0 L5 0
    LOCALVARIABLE condition Z L0 L5 1
    LOCALVARIABLE x Ljava/lang/Object; L3 L1 2
    MAXSTACK = 2
    MAXLOCALS = 3
}

Обратите внимание, что переменная x, созданная в строке 7, сохраняется в слоте переменной 2, который по-прежнему доступен в байт-коде, соответствующем строке 10.

Нет никаких указаний на то, как язык Java должен быть скомпилирован в байт-код, кроме нескольких примеров того, как правильно компилировать некоторые языковые конструкции. Однако компилятору Java разрешено удалять неиспользуемые переменные. Например. если x был назначен, но нигде не использовался, компилятор может удалить этот код. Точно так же компилятор встраивает все статические константы.

1
ответ дан 7 December 2019 в 03:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: