Подконтексты в Java - отдельные строки в стеке? - PullRequest
7 голосов
/ 17 июня 2010

В Java это так:

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

Что мне интересно, так это то, что x ограничен областью применения if только функцией компилятора Java или x фактически удален из стека после if -statement

Ответы [ 4 ]

7 голосов
/ 17 июня 2010

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

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

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

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

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

2 голосов
/ 17 июня 2010

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

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

1 голос
/ 17 июня 2010

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

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

  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 был назначен, но нигде не используется, компилятору разрешено отбрасывать этот код.Точно так же компилятор включает все статические константы.

0 голосов
/ 17 июня 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...