1、你是不是开来很多线程,然后这些线程还递归了?原因应该是栈被你用完了吧。
2、死循环本身是不会StackOverflow的,只有无限递归的时候会出现。原则上循环嵌套次数本身是没有限制的,限制的是占用的栈空间,如果你的函数里定义了很多很多变量,栈空间就会用完得比较快。
Java里面有没有这种语法不清楚,C#中间可以把struct定义成整个展开的形式,这样一个struct可能就占很大的空间,而且是unboxing的,放到栈上可能一层就会导致StackOverflow……
3、 支持 "循环嵌套次数本身是没有限制的",这个应该是错的.我看过官方文档,里面说是因为嵌套的层次太深导致的.但是嵌套层次要去到什么深度才引起java.lang.StackOverflowError,我现在还没找到.
我的函数嵌套了1k层左右,当初我也以为是栈空间占用太多了导致的,所以把不必要的变量都去掉,单纯的去递归,但是还是报StackOverflowError.最后把算法改成不用递归,用循环,问题就解决了.
4、递归就算什么变量都不要也是消耗栈空间的,每次调用都要在栈里面压一大堆乱七八糟的东西,比如说返回地址,比如说参数,还可能有执行上下文等等。
5、JVM里会有两种StackOverflowError, 一种是对应JVM stack, 一种是对应Native Method stack. 我们一般说的都是JVM stack.
每一个JVM线程维护自己的JVM stack. JVM stack里面存放 JVM栈帧. 栈帧中存放 数据和中间结果(本地变量数组, 操作符栈, 和对runtime 常量池的引用). 这些数据都比较小(对象都在堆中, 栈帧仅存放对象引用), 所以想单纯通过 在栈帧中存放大数据的方法 去引入StackOverflowError, 基本是不现实的.一般都是因为方法调用嵌套层数过大.
http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-2.html#jvms-2.5.2
JVM stack的大小是可以调节的, sun的windows jvm6 x64,jvm栈默认大小为1024k.可以通过-Xss1024k来调节.
http://www.oracle.com/technetwork/java/hotspotfaq-138619.html#threads_oom
做一点实验:
private int aa=0; private void aaa(){ System.out.println(aa++); aaa(); } @Test public void test3243(){ aaa(); }
测试结果: -server -Xss128k 输出946时溢出java栈 -server -Xss512k 输出5418时溢出java栈 -server -Xss1280k 输出14363时溢出java栈 -server -Xss12800k 输出252223时溢出java栈
6、函数栈溢出 就会出现这个错误 一些语言是可以设置递归的最大深度的(比如Python) 如果体验过这个 你就明白这里的溢出是咋回事了