Grz*_*zki 31 java stack-overflow
观察StackOverflowError时如何检索完整的调用堆栈?
考虑这个简单的例子:
public class Overflow {
public Overflow() {
new Overflow();
}
public static void a() {
new Overflow();
}
public static void main(String[] argv) {
a();
}
}
Run Code Online (Sandbox Code Playgroud)
现在报告的错误是:
Exception in thread "main" java.lang.StackOverflowError
at Overflow.<init>(Overflow.java:11)
[last line repeated many times]
Run Code Online (Sandbox Code Playgroud)
但我无法在堆栈跟踪中看到main和a方法.我的猜测是因为溢出,堆栈中的最新条目取代了最旧的条目(?).
现在,如何在输出中获取a和main堆栈条目?
其背景是,我得到了一个的StackOverflowError(但是这不是一个无限递归,因为增加堆栈大小时,它不会发生),它是很难发现代码中的问题.我只获取了多行java.util.regex.Pattern代码而不是代码所谓的信息.应用程序太复杂,无法在每次调用Patterns时设置断点.
Cyr*_* Ka 40
JVM具有1024个条目的人为限制,您可以在异常或错误的堆栈跟踪中拥有这些条目,可能在发生时节省内存(因为VM必须分配内存来存储堆栈跟踪).
幸运的是,有一个标志允许增加此限制.只需使用以下参数运行程序:
-XX:MaxJavaStackTraceDepth=1000000
Run Code Online (Sandbox Code Playgroud)
这将打印多达100万个堆栈跟踪条目,这应该绰绰有余.也可以将此值0设置为将条目数设置为无限制.
此非标准JVM选项列表提供了更多详细信息:
最大.没有.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)
Run Code Online (Sandbox Code Playgroud)
这样,即使实际堆栈跟踪长度超过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.
}
}
Run Code Online (Sandbox Code Playgroud)
从本质上讲,这将创建并抛出一个新的StackOverflowError,丢弃最后一个条目,因为每个条目将比前一个条目向上发送一级(这可能需要几秒钟,因为必须创建所有这些错误).当堆栈跟踪将减少到1023个元素时,它只是被重新抛出.
最终,这将在堆栈跟踪的底部打印1023行,这不是完整的堆栈跟踪,但可能是它最有用的部分.
| 归档时间: |
|
| 查看次数: |
8720 次 |
| 最近记录: |