2010-01-24 111 views
55

我正在運行一個我在Eclipse中用Java編寫的程序。該程序對於非常大的輸入具有非常深的遞歸級別。對於較小的輸入程序運行正常時,卻給出了大投入,我得到以下錯誤:Java堆棧溢出錯誤 - 如何在Eclipse中增加堆棧大小?

Exception in thread "main" java.lang.StackOverflowError 

這個問題能得到解決,通過增加Java堆棧大小,如果是這樣,我怎麼做這在Eclipse?

更新:

@喬恩飛碟雙向

的代碼是爲了建立一個數據結構遞歸遍歷解析樹。因此,例如,代碼將使用分析樹中的一個節點來做一些工作,並在節點的兩個子節點上調用它自己,並將它們的結果組合起來以給出樹的總體結果。

遞歸的總深度取決於解析樹的大小,但代碼似乎失敗(沒有更大的棧)時,遞歸調用的次數進入了1000。

而且我敢肯定,因爲一個錯誤的代碼不會失敗,因爲它適用於小的投入。

+7

這裏有什麼錯... stackoverflow(.com)不是錯誤! :-) – 2010-01-24 14:37:31

回答

72

打開您的應用程序(運行/運行配置的運行配置 ...,然後在'Java應用程序'中查找應用程序條目)。

參數片具有一個文本框VM參數,輸入-Xss1m(或最大堆棧大小更大的參數)。默認值是512 kByte(SUN JDK 1.5 - 不知道它是否因供應商和版本而異)。

+2

請注意以下問題:http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6316197 – 2010-01-24 15:02:40

10

在VM參數中添加標誌-Xss1024k

您也可以通過使用-Xss1m例如增加堆棧大小mb

37

可以是通過增加堆棧大小固化 - 但更好的解決辦法是制定出如何避免遞歸這麼多。遞歸解決方案總是可以轉換爲迭代解決方案 - 這將使您的代碼更加乾淨地擴展到更大的輸入。否則,你真的會猜測提供了多少堆棧,這可能不是從輸入中顯而易見的。

你真的確認它的失敗是由於輸入,而不是在代碼中的錯誤的大小,順便說一下?這個遞歸有多深?

編輯:好的,在看到更新,我會親自嘗試重寫它避免使用遞歸。通常有一個Stack<T>的「事情仍然存在」是刪除遞歸的一個很好的起點。

+4

..或通過尾遞歸。 – BalusC 2010-01-24 13:46:43

+0

我不記得jvms上的尾遞歸狀態。線索評論。 – 2010-01-24 14:08:34

+1

JVM尚未作爲規則優化尾遞歸。我相信這是將JVM推廣到非Java語言需要解決的問題之一。 – 2010-01-24 15:01:46

3

您需要在Eclipse內部具有啓動配置才能調整JVM參數。

有兩種F11或Ctrl-F11運行程序後,運行打開啓動配置 - >運行配置...,然後在「Java應用程序」打開你的程序。選擇Arguments窗格,您將在其中找到「VM參數」。

這是-Xss1024k去的地方。

如果您希望啓動配置是工作區中的文件(因此您可以右鍵單擊並運行它),請選擇Common窗格,然後選中Save as - > Shared File複選框並瀏覽到您想要的位置啓動文件。我通常有他們在一個單獨的文件夾,因爲我們檢查他們到CVS。

5

我也有同樣的問題,而使用XSOM庫解析架構定義文件(XSD),

我能夠增加堆棧內存高達208Mb則表明heap_out_of_memory_error爲此我能只增加高達320MB。

最終配置爲-Xmx320m -Xss208m,但後來又運行了一段時間並失敗。

我的函數以遞歸方式打印模式定義的整個樹,令人驚訝的是,輸出文件跨越了820Mb,用於4 Mb(Aixm庫)的定義文件,後者又使用了50 Mb的模式定義庫(ISO gml)。

與此我相信我必須避免遞歸,然後開始迭代和其他方式來表示輸出,但我沒有什麼麻煩將所有遞歸轉換爲迭代。

2

當參數-Xss沒有做這項工作從嘗試刪除臨時文件:

c:\Users\{user}\AppData\Local\Temp\. 

這奏效了我。

0

看Morris按順序樹遍歷,它使用常量空間並運行在O(n)(最多比正常遞歸遍歷長3倍 - 但在空間上節省很多)。如果節點是可修改的,則可以在回溯到其根目錄時(通過直接寫入節點)保存子樹的計算結果。