为了账号安全,请及时绑定邮箱和手机立即绑定

如何增加Java堆栈的大小?

如何增加Java堆栈的大小?

慕虎7371278 2019-06-16 14:32:24
如何增加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上面,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)-xss 5米就足够了fact(1 << 17)-Xss7m就够了fact(1 << 18)-Xss9m就够了fact(1 << 19)-Xss 18m就够了fact(1 << 20)-Xss35m可以满足fact(1 << 21)-Xss68m可以满足fact(1 << 22)-Xss129m足以fact(1 << 23)-Xss258m足以满足fact(1 << 24)-Xss 515米就够了fact(1 << 25)从上面的数字来看,Java似乎为上面的函数使用了大约16个字节的堆栈帧,这是合理的。上面的枚举包含就够了而不是就够了,因为堆栈要求不是确定性的:使用相同的源文件和相同的源文件多次运行它。-Xss...有时成功,有时产生StackOverflowError..例如,1<20,-Xss18m10中的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));   }}FYI,正如上面的迭代解决方案所示,fact函数无法计算65以上数字的确切阶乘(实际上,甚至超过20),因为java内建类型long会溢出。重构fact所以它会返回一个BigInteger而不是long对于大量的输入也会产生精确的结果。
查看完整描述

3 回答

?
www说

TA贡献1775条经验 获得超8个赞

嗯.。它适用于我,而且堆栈的容量远远小于999 MB:

> java -Xss4m Test0

(Windows JDK 7,构建17.0-B05客户端VM,Linux JDK 6-与您发布的版本信息相同)


查看完整回答
反对 回复 2019-06-16
?
qq_花开花谢_0

TA贡献1835条经验 获得超7个赞

我假设您是通过堆栈跟踪中的重复行计算“1024的深度”吗?

显然,Throwable中的堆栈跟踪数组长度似乎限制在1024。尝试以下程序:

public class Test {

    public static void main(String[] args) {

        try {
            System.out.println(fact(1 << 15));
        }
        catch (StackOverflowError e) {
            System.err.println("true recursion level was " + level);
            System.err.println("reported recursion level was " +
                               e.getStackTrace().length);
        }
    }

    private static int level = 0;
    public static long fact(int n) {
        level++;
        return n < 2 ? n : n * fact(n - 1);
    }}


查看完整回答
反对 回复 2019-06-16
?
开心每一天1111

TA贡献1836条经验 获得超13个赞

如果您想使用线程堆栈大小,则需要查看HotSpot JVM上的-XSS选项。这在非HotSpot VM上可能有所不同,因为JVM的-X参数是特定于发行版的,IIRC。

在热点上,这看起来就像java -Xss16M如果你想要16米的尺寸的话。

类型java -X -help如果希望看到所有特定于发行版的JVM参数,则可以传入。我不确定这在其他JVM上是否同样工作,但它会打印所有HotSpot特定的参数。

值得注意的是,我建议限制您在Java中使用递归方法。优化它们并不太好-比如JVM不支持尾递归(参见JVM是否阻止尾调用优化?)。尝试重构上面的阶乘代码,以使用while循环而不是递归方法调用。


查看完整回答
反对 回复 2019-06-16
  • 3 回答
  • 0 关注
  • 2018 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信