如何扩展Java堆栈跟踪的大小以查看堆栈的底部? (触发堆栈溢出)

在Java中,有没有办法查看完整的,未截断的堆栈跟踪(例如,通过增加记录的帧数),或以其他方式获取堆栈跟踪的底部 ? 通常情况下,堆栈跟踪从顶部以1024帧的价格被截断,但是对于堆栈溢出问题,这是相当没价值的,因为您确实需要查看是谁进行了触发递归的调用,靠近底部。 更好的是在堆栈中间截断,但显然Sun的JVM不够聪明,无法做到这一点。

甚至可能是一些特殊的Sun特定标志? 我尝试将堆栈大小减小到允许的最小值(-Xss1000),但仍然超过1024帧。

在我的例子中,我正在尝试调试Hadoop映射器中发生的堆栈溢出,但仅限于在非常大的输入上运行时。 我假设问题来了,因为递归操作(Scala的foldRight )正在一个非常大的链表上完成,我需要非递归地重写它……但我需要知道是谁调用了foldRight 。 这是一个直接和间接在很多地方调用的基本例程,我正在使用很多很多代码,所以这是非常不明显的。

试试-XX:MaxJavaStackTraceDepth JVM选项。

以下是Stas博客的描述

最大。 没有。 Javaexception的堆栈跟踪中的行(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进行测试)。

您可以自己迭代堆栈跟踪

 Throwable t = for(StackTraceElement ste: t.getStackTrace()) { // is it a repeat?? } 

默认的printStackTrace将打印已记录的每个级别。 您的问题是堆栈太深,无法放入堆栈跟踪中。

你能尝试减少堆栈大小吗?

如果您进入可疑堆栈溢出之前可以访问该调用则可以生成额外的堆栈跟踪,例如new Exception().getStackTrace 。 请注意, foldRight本身不会产生无限递归。 也许你只是耗尽内存,尝试增加JVM的堆栈大小。