如何增加Java堆栈的大小?
我问这个问题是为了了解如何在JVM中增加运行时调用栈的大小。 我已经得到了这个问题的答案。 另外,关于Java如何处理需要大规模运行时堆栈的情况,得到了很多有用的答案和评论。 我补充了我的问题和回答的摘要。
最初,增加jvm堆栈的大小,即使运行此类程序,也可以将堆栈overflow error.public class TT {
publicstaticlongfact(intn ) {
返回nn
}
publicstaticvoidmain (字符串[ ] args ) {
system.out.println(fact(1
}
适当的配置设置是具有足够的java -Xss .值的命令行标志。 在节目TT上,OpenJDK的JVM是这样工作的。 $javacTT.java
$java-Xss4mTT
其中一个答案也指出,-X .标记与实现有关。 我是Java版本'1.6.0_ 18 '开放jdkruntimeenvironment (iced tea 61.8.1 ) ) 6b 18-1.8.1-0 Ubuntu 1至8.04.3
服务器虚拟机(构建16.0-B13,混合模式) )。
也可以为一个线程指定一个大堆栈(请参见其中一个答案)。 这是建议的java -Xss,以避免在不需要内存的线程上浪费内存。
因为我很好奇上面的程序需要多少堆栈,所以我运行它来增加n。 -xss4m就足够了
fact(115 )。
-xss 5米就足够了
fact(117 )。
-Xss7m就足够了
fact(118 )。
-Xss9m就足够了
fact(119 )。
-Xss 18m就足够了
fact(120 )。
-Xss35m米令人满意
fact(121 )。
-Xss68m令人满意
fact(122 )。
-Xss129m米就足够了
fact(123 )。
-Xss258m米就足够满足了
fact(124 )。
-Xss 515米就足够了
fact(125 )。
从上面的数字来看,Java似乎为了上面的函数使用了大约16字节的堆栈帧。 这是合理的。
上面的枚举包含的内容不够充分,因为堆栈要求不确定。 使用同一源文件和同一源文件多次运行。 -Xss .可能成功,也可能发生堆栈溢出错误。 例如,120、-Xss18m10中的7次就足够了。 另外,-Xss19m也不一定足够,但-Xss20m就足够了。 总共100次跑完100次。 垃圾收集、JIT启动和其他什么会引起这种不确定的行为吗?
中打印的堆栈跟踪。 堆栈溢出错误器仅显示运行时堆栈中最新的1024个元素。 下面的答案说明了如何计算已达到的准确深度。 这可能远远大于1024。
许多受访者指出,考虑实现不太需要备用堆栈的相同算法是一种很好的安全编码实践。 通常,可以将一组递归函数转换为迭代函数。 堆中填充的堆栈对象,而不是运行时堆栈)。 这个特殊的fact功能很容易转换。 我的反复版本如下。 publicclassTTIterative{
publicstaticlongfact(intn ) {
if(n )
if(n65 )返回0; //enoughpowersof 2智能产品工具包(long ) 0。
longf=2;
for(inti=3; i=n; I ) {
f*=i;
}
返回函数;
}
publicstaticvoidmain (字符串[ ] args ) {
system.out.println(fact(1
}
FYI,正如上面的迭代解决方案所示,fact函数无法计算65或更大数字的精确阶乘。 实际上,有时会超过20个。 因为java嵌入式长整型会溢出。 重建fact时,将返回BigInteger而不是long,对于大量输入也可以获得准确的结果。