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