Как увеличить размер стека Java?

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

Первоначально я хотел увеличить размер стека JVM, чтобы такие программы, как запускались без StackOverflowError .

public class TT {
  public static long fact(int n) {
    return n < 2 ? 1 : n * fact(n - 1);
  }
  public static void main(String[] args) {
    System.out.println(fact(1 << 15));
  }
}

Соответствующий параметр конфигурации - ] java -Xss ... Флаг командной строки с достаточно большим значением. Для программы TT выше она работает следующим образом с JVM OpenJDK:

$ javac TT.java
$ java -Xss4m TT

В одном из ответов также указано, что -X ... флаги зависят от реализации. Я использовал

java version "1.6.0_18"
OpenJDK Runtime Environment (IcedTea6 1.8.1) (6b18-1.8.1-0ubuntu1~8.04.3)
OpenJDK 64-Bit Server VM (build 16.0-b13, mixed mode)

. Также можно указать большой стек только для одного потока (см. В одном из ответов, как). Это рекомендуется вместо java -Xss ... чтобы не тратить память на потоки, которые в ней не нуждаются.

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

  • -Xss4m может будет достаточно для fact (1 << 15)
  • -Xss5m может быть достаточно для fact (1 << 17)
  • -Xss7m может быть достаточно для fact (1 << 18 )
  • -Xss9m может быть достаточно для fact (1 << 19)
  • -Xss18m может быть достаточно для fact (1 << 20)
  • -Xss35m может быть достаточно для fact (1 << 21)
  • -Xss68m может быть достаточно для fact (1 << 22)
  • -Xss129m может быть достаточно для fact (1 << 23)
  • -Xss258m может быть достаточно для fact (1 << 24)
  • -Xss515m может быть достаточно для факта (1 << 25)

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

Перечисление выше содержит может быть достаточно вместо достаточно , потому что требование стека не является детерминированным: запускать его несколько раз с одним и тем же исходным файлом и одним и тем же -Xss ... иногда удается, а иногда выдает ошибку StackOverflowError . Например для 1 << 20 -Xss18m было достаточно в 7 прогонах из 10, и -Xss19m тоже не всегда было достаточно, но -Xss20m было достаточно (всего 100 работает из 100). Вызывает ли это недетерминированное поведение сборка мусора, срабатывание JIT или что-то еще?

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

Многие ответившие указали, что хорошей и безопасной практикой программирования является рассмотрение альтернативных, менее требовательных к стеку реализаций. того же алгоритма. В основном, можно преобразовать набор рекурсивных функций в итерационные функции (используя, например, объект Stack , который заполняется в куче, а не в стеке времени выполнения). Для этой конкретной функции fact ее довольно легко преобразовать. Моя итерационная версия будет выглядеть так:

public class TTIterative {
  public static long fact(int n) {
    if (n < 2) return 1;
    if (n > 65) return 0;  // Enough powers of 2 in the product to make it (long)0.
    long f = 2;
    for (int i = 3; i <= n; ++i) {
      f *= i;
    }
    return f;
  }
  public static void main(String[] args) {
    System.out.println(fact(1 << 15));
  }
}

К вашему сведению, как показано в приведенном выше итеративном решении, функция fact не может вычислить точный факториал чисел больше 65 (фактически, даже больше 20), потому что Java построила -in тип long приведет к переполнению. Рефакторинг факта , чтобы он возвращал BigInteger вместо long , также даст точные результаты для больших входных данных.

114
задан pts 20 March 2014 в 16:22
поделиться