如何增加Java堆栈的大小?
我问这个问题是为了了解如何在JVM中增加运行时调用堆栈的大小。我得到了一个答案,我也得到了许多有用的答案和注释,这些答案和注释与Java如何处理需要大型运行时堆栈的情况有关。我把我的问题扩展到了回答的摘要 最初,我想增加JVM堆栈的大小,以便像这样的程序在运行时不使用如何增加Java堆栈的大小?,java,stack,stack-overflow,Java,Stack,Stack Overflow,我问这个问题是为了了解如何在JVM中增加运行时调用堆栈的大小。我得到了一个答案,我也得到了许多有用的答案和注释,这些答案和注释与Java如何处理需要大型运行时堆栈的情况有关。我把我的问题扩展到了回答的摘要 最初,我想增加JVM堆栈的大小,以便像这样的程序在运行时不使用StackOverflowerError public class TT { public static long fact(int n) { return n < 2 ? 1 : n * fact(n - 1);
StackOverflowerError
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));
}
}
其中一个答案还指出,-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…
上使用此选项,以避免为不需要它的线程浪费内存
我很好奇上面的程序到底需要多大的堆栈,所以我运行了它
- -Xss4m对于
fact(1Hmm)来说已经足够了。它对我来说非常有效,并且堆栈的大小远小于999MB:
> java -Xss4m Test 0
(Windows JDK 7、build 17.0-b05 client VM和Linux JDK 6-与您发布的版本信息相同)如果您想使用线程堆栈大小,您需要查看热点JVM上的-Xss选项。在非热点VM上可能有所不同,因为JVM的-X参数是特定于分发的,IIRC 在Hotspot上,如果您想制作16兆的尺寸,这看起来像
如果您想查看可以传入的所有特定于发行版的JVM参数,请键入java-Xss16M
。我不确定这是否适用于其他JVM,但它会打印所有特定于热点的参数java-X-help
值得一提的是,我建议您在Java中限制递归方法的使用。它在优化递归方法方面不是太好,因为JVM不支持尾部递归(请参阅)。请尝试重构上面的阶乘代码,使用while循环而不是递归方法调用。我假设您计算了“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); } }
公共类测试{ 公共静态void main(字符串[]args){ 试一试{
System.out.println(事实(1奇怪!您是说要生成1的递归控制进程内堆栈大小的唯一方法是启动一个新的
。但是您也可以通过使用线程
参数创建一个自调用子Java进程来控制-Xss
public class TT { private static int level = 0; public static long fact(int n) { level++; return n < 2 ? n : n * fact(n - 1); } public static void main(String[] args) throws InterruptedException { Thread t = new Thread(null, null, "TT", 1000000) { @Override public void run() { try { level = 0; 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); } } }; t.start(); t.join(); try { level = 0; 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); } } }
公共类TT{ 私有静态int级别=0; 公共静态长事实(int n){ 级别++; 返回n<2?n:n*事实(n-1); } 公共静态void main(字符串[]args)引发InterruptedException{ 线程t=新线程(null,null,“TT”,1000000){ @凌驾 公开募捐{ 试一试{ 级别=0;
事实上,很难给出一个合理的解决方案,因为你渴望避免所有合理的方法。重构一行代码是一个可行的解决方案 注意:使用-Xss设置每个线程的堆栈大小,这是一个非常糟糕的主意 另一种方法是字节码操作,以如下方式更改代码:public static long fact(int n) { return n < 2 ? n : n > 127 ? 0 : n * fact(n - 1); }
公共静态长事实(int n){ 返回n<2?n:n>127?0:n*事实(n-1); }
假设n>127的每个答案都是0。这样可以避免更改源代码。其他海报已经指出了如何增加内存,并且您可以记忆呼叫。我建议,对于许多应用程序,您可以使用斯特林公式来近似大n!非常快,几乎没有内存占用 以这篇文章为例,它对函数和代码进行了一些分析: 我做了,这就像问题一样,但有50000面额(硬币)。我是,我不在乎。我只知道-xss选项没有效果——我总是在1024个堆栈帧后失败(可能是scala在交付到java或printStackTrace限制方面做得不好。我不知道).无论如何,这是一个坏选项。您不希望应用程序中的所有线程都是异常的。但是,我用新线程(堆栈大小)做了一些实验。这确实有效def measureStackDepth(ss: Long): Long = { var depth: Long = 0 val thread: Thread = new Thread(null, new Runnable() { override def run() { try { def sum(n: Long): Long = {depth += 1; if (n== 0) 0 else sum(n-1) + 1} println("fact = " + sum(ss * 10)) } catch { case e: StackOverflowError => // eat the exception, that is expected } } }, "deep stack for money exchange", ss) thread.start() thread.join() depth } //> measureStackDepth: (ss: Long)Long for (ss <- (0 to 10)) println("ss = 10^" + ss + " allows stack of size " -> measureStackDepth((scala.math.pow (10, ss)).toLong) ) //> fact = 10 //| (ss = 10^0 allows stack of size ,11) //| fact = 100 //| (ss = 10^1 allows stack of size ,101) //| fact = 1000 //| (ss = 10^2 allows stack of size ,1001) //| fact = 10000 //| (ss = 10^3 allows stack of size ,10001) //| (ss = 10^4 allows stack of size ,1336) //| (ss = 10^5 allows stack of size ,5456) //| (ss = 10^6 allows stack of size ,62736) //| (ss = 10^7 allows stack of size ,623876) //| (ss = 10^8 allows stack of size ,6247732) //| (ss = 10^9 allows stack of size ,62498160)
def measureStackDepth(ss:Long):Long={ 变量深度:Long=0 val thread:thread=new thread(null,new Runnable(){ 覆盖def运行(){ 试一试{ def sum(n:Long):Long={depth+=1;if(n==0)0 else sum(n-1)+1} println(“事实=”+总和(ss*10)) }抓住{ 案例e:StackOverflowerError=>//吃掉预期的异常 } } },“货币兑换的深层堆栈”,ss) thread.start() thread.join() 深度 }//>测量堆叠深度:(ss:长)长 对于(ss measureStackDepth((scala.math.pow(10,ss)).toLong)) //>事实=10 //|(ss=10^0允许堆栈大小为11) //|事实=100 //|(ss=10^1允许堆栈大小为101) //|事实=1000 //|(ss=10^2允许大小为1001的堆栈) //|事实=10000 //|(ss=10^3允许堆叠大小,10001) //|(ss=10^4允许堆叠大小,1336) //|(ss=10^5允许堆栈大小,5456) //|(ss=10^6允许堆叠大小,62736) //|(s)
public static long fact(int n) { return n < 2 ? n : n > 127 ? 0 : n * fact(n - 1); }
def measureStackDepth(ss: Long): Long = { var depth: Long = 0 val thread: Thread = new Thread(null, new Runnable() { override def run() { try { def sum(n: Long): Long = {depth += 1; if (n== 0) 0 else sum(n-1) + 1} println("fact = " + sum(ss * 10)) } catch { case e: StackOverflowError => // eat the exception, that is expected } } }, "deep stack for money exchange", ss) thread.start() thread.join() depth } //> measureStackDepth: (ss: Long)Long for (ss <- (0 to 10)) println("ss = 10^" + ss + " allows stack of size " -> measureStackDepth((scala.math.pow (10, ss)).toLong) ) //> fact = 10 //| (ss = 10^0 allows stack of size ,11) //| fact = 100 //| (ss = 10^1 allows stack of size ,101) //| fact = 1000 //| (ss = 10^2 allows stack of size ,1001) //| fact = 10000 //| (ss = 10^3 allows stack of size ,10001) //| (ss = 10^4 allows stack of size ,1336) //| (ss = 10^5 allows stack of size ,5456) //| (ss = 10^6 allows stack of size ,62736) //| (ss = 10^7 allows stack of size ,623876) //| (ss = 10^8 allows stack of size ,6247732) //| (ss = 10^9 allows stack of size ,62498160)
--driver-java-options -Xss512m