JVM有1024个条目的人为限制,你可以在一个异常或错误的堆栈跟踪,可能发生时以节省内存(因为虚拟机必须分配的内存来存储堆栈跟踪)。
幸运的是,有一个标志允许增加此限制。用下面的参数运行你的程序:
-XX:MaxJavaStackTraceDepth=1000000
这将打印多达100万条堆栈跟踪,这应该是绰绰有余。也可以将此值设置为-1
以将条目数设置为无限制。
This list of non-standard JVM options提供了更多的细节:
最大。没有。 Java异常堆栈跟踪中的行数(0表示全部为 )。使用Java> 1.6时,值0实际上表示0.值-1或任何 必须指定负数以打印所有堆栈(在Windows上使用 1.6.0_22,1.7.0进行测试)。对于Java < = 1.5,值0意味着所有内容,负数上的JVM扼流圈(在Windows的 窗口上使用1.5.0_22进行测试)。
用此标志运行问题的样本给出了以下结果:
Exception in thread "main" java.lang.StackOverflowError
at Overflow.<init>(Overflow.java:3)
at Overflow.<init>(Overflow.java:4)
at Overflow.<init>(Overflow.java:4)
at Overflow.<init>(Overflow.java:4)
(more than ten thousand lines later:)
at Overflow.<init>(Overflow.java:4)
at Overflow.<init>(Overflow.java:4)
at Overflow.a(Overflow.java:7)
at Overflow.main(Overflow.java:10)
这种方式,你可以找到抛出错误代码的原始调用方,即使实际的堆栈跟踪长度超过1024行。
如果你不能使用这个选项,还有另外一种方法,如果你在这样的递归函数中,并且你可以修改它。如果您添加以下的try-catch:
public Overflow() {
try {
new Overflow();
}
catch(StackOverflowError e) {
StackTraceElement[] stackTrace = e.getStackTrace();
// if the stack trace length is at the limit , throw a new StackOverflowError, which will have one entry less in it.
if (stackTrace.length == 1024) {
throw new StackOverflowError();
}
throw e; // if it is small enough, just rethrow it.
}
}
从本质上讲,这将创建并抛出一个新的StackOverflowError
,丢弃的最后一项,因为每个人都会比前一个被发送一个级别(这可能需要几秒钟,因为所有这些错误必须被创建)。当堆栈跟踪将被减少到1023个元素时,它就会被重新抛出。
最终,这将在堆栈跟踪的底部打印1023行,这不是完整的堆栈跟踪,但可能是最有用的部分。
鉴于您可以增加堆栈大小并消失,您是否可以尝试减小堆栈大小并查看是否允许您查看更多堆栈跟踪?无法记住您如何控制JVM中的堆栈大小,以及是否允许将它设置得足够小,但它可能有助于诊断问题。 – 2011-03-02 10:10:20
@Tom,堆栈大小由新的Thread(ThreadGroup组,Runnable target,String name,long stackSize)控制。 – bestsss 2011-03-02 10:26:37
哦,好的。好主意:-( – 2011-03-02 10:26:59