当前位置: 首页 > 面试题库 >

如何增加Java堆栈大小?

公子昂
2023-03-14
问题内容

我问了这个问题,以了解如何增加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上面的程序,它可以与OpenJDK的JVM一起工作:

$ 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足以满足 fact(1 << 25)

从上面的数字看来,Java为上述功能使用的每个堆栈帧大约有16个字节,这是合理的。

上面包含的枚举可能足够,而不是足够,因为堆栈要求不是确定性的:使用相同的源文件多次运行该堆栈,并且-Xss...有时成功一次,有时会产生a StackOverflowError。例如,对于1 << 20,-Xss18m在10中有7个就用完了,-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内置类型long会溢出。进行重构,fact以使其返回a BigInteger而不是long大型输入也能产生准确的结果。


问题答案:

它对我有用,堆栈少于999MB:

> java -Xss4m Test
0

(Windows JDK 7,内部版本17.0-b05客户端VM和Linux JDK 6-与你发布的版本信息相同)



 类似资料:
  • 问题内容: 我正在运行一个用Java在Eclipse中编写的程序。对于很大的输入,该程序具有很深的递归级别。对于较小的输入,程序运行正常,但是在给出较大的输入时,出现以下错误: 可以通过增加Java堆栈大小来解决此问题,如果可以,那么如何在Eclipse中做到这一点? 更新: @乔恩·斯基特 该代码递归地遍历解析树以建立数据结构。因此,例如,代码将使用解析树中的一个节点来做一些工作,并在该节点的两

  • 这与其他关于Node中错误消息的问题不同,错误消息中写着RangeError:超出最大调用堆栈大小,因为我确切地知道为什么会收到这条错误消息。它的发生是因为我在递归,事实上递归了很多次。 谢谢。

  • 问题内容: 这与有关Node中读取 RangeError 的错误消息的其他问题不同 :超出最大调用堆栈大小的 原因是我确切知道为什么收到此错误消息。之所以会这样,是因为我要递归,实际上递归很多。 谢谢。 问题答案: 来自: 更新:如注释所示,即使帮助文本仍列出了该选项,您也需要在节点v0.10.x中使用它。

  • 问题内容: 我收到以下错误: 问题答案: 以下是一些可用来更改堆大小的选项。

  • 问题内容: 如何增加Java中的堆大小? 问题答案: 你可以在32位系统上增加到4GB。如果你使用的是64位系统,则可以更高。如果你选择不正确,无需担心,如果你在32位系统上要求5g,则Java会抱怨值无效并退出。 正如其他人发布的那样,使用cmd-line标志-例如 你可以通过键入java -X来获得完整列表(或者无论如何都接近完整列表)。 使用命令行选项可以增加JVM分配的堆大小。这里有3个选

  • 问题内容: 我正在尝试在netbeans中的Java中构建将近110000个单词的词典特里。我的代码运行良好,但是给出了如下异常: 我想知道是否有人可以帮助我增加netbeans中的Java堆空间。 问题答案: 您可以在NetBeans的项目属性->运行-> VM选项中进行设置。 右键点击您的项目“ Properties ” 选择“ 运行 ”类别。 在“ VM Options* ”文本框中输入参数