Стек = 4 в Java байткод. Как работает Java компилятор вычислить значение 4? (Глубина стека)

Юнесс:

Java код:

public class SimpleRecursion {

    public int factorial(int n) {
        if (n == 0) {
            return 1;
        }
        return n * factorial(n - 1);
    }

}

Дает следующий байт-код для факторного метода (я выполнил javap для его генерации):

public int factorial(int); 
descriptor: (I)I 
flags: ACC_PUBLIC 
Code:   
  stack=4, locals=2, args_size=2
     0: iload_1
     1: ifne          6
     4: iconst_1
     5: ireturn
     6: iload_1
     7: aload_0
     8: iload_1
     9: iconst_1
    10: isub
    11: invokevirtual #2                  // Method factorial:(I)I
    14: imul
    15: ireturn   
  LineNumberTable:
    line 4: 0
    line 5: 4
    line 7: 6   
  StackMapTable: number_of_entries = 1
    frame_type = 6 /* same */

Я понимаю , что в пятой строке в блоке выше, стек = 4 означает , что стек может иметь не более 4 -х объектов .

Но как компилятор вычислить, что?

Хольгер:

Поскольку начальное состояние стека, а также влияния каждой команды на нем хорошо известно, можно точно предсказать, какой тип элементов будет в стеке операндов в любое время:

[ ]            // initially empty
[ I ]          0: iload_1
[ ]            1: ifne          6
[ I ]          4: iconst_1
[ ]            5: ireturn
[ I ]          6: iload_1
[ I O ]        7: aload_0
[ I O I ]      8: iload_1
[ I O I I ]    9: iconst_1
[ I O I ]     10: isub
[ I I ]       11: invokevirtual #2   // Method factorial:(I)I
[ I ]         14: imul
[ ]           15: ireturn   

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

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

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

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

рекомендация

отhttp://43.154.161.224:23101/article/api/json?id=278645&siteId=1